Introduction
This notebook contains analyses from the MEDAL study, assessing memory bias in remitted and depressed individuals. The pre-registration for the main analyses, as well as a preprint version of the accompanying article can be found here as well. The main aim of the current work was to examine how three groups (control, remitted, depressed) differ in terms of emotional memory dynamics in a real-life setting.
#Load packages
renv::activate()
* Project 'Z:/medal_membias' loaded. [renv 0.15.5]
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(janitor)
Attaching package: ‘janitor’
The following objects are masked from ‘package:stats’:
chisq.test, fisher.test
library(readxl)
library(data.table)
data.table 1.14.4 using 8 threads (see ?getDTthreads). Latest news: r-datatable.com
Attaching package: ‘data.table’
The following objects are masked from ‘package:dplyr’:
between, first, last
library(ggplot2)
library(psych)
Attaching package: ‘psych’
The following objects are masked from ‘package:ggplot2’:
%+%, alpha
library(devtools)
Loading required package: usethis
library(pastecs)
Attaching package: ‘pastecs’
The following objects are masked from ‘package:data.table’:
first, last
The following objects are masked from ‘package:dplyr’:
first, last
library(cli)
library(lmerTest) #linear mixed models
Loading required package: lme4
Loading required package: Matrix
Attaching package: ‘lmerTest’
The following object is masked from ‘package:lme4’:
lmer
The following object is masked from ‘package:stats’:
step
library(performance) #fits of residuals
library(DescTools)
Registered S3 method overwritten by 'DescTools':
method from
print.palette wesanderson
Attaching package: ‘DescTools’
The following objects are masked from ‘package:psych’:
AUC, ICC, SD
The following object is masked from ‘package:data.table’:
%like%
library(tidyr) # Separate trigger column
Attaching package: ‘tidyr’
The following objects are masked from ‘package:Matrix’:
expand, pack, unpack
The following object is masked from ‘package:pastecs’:
extract
library(sjPlot) # for nice tables and interaction plots
Learn more about sjPlot with 'browseVignettes("sjPlot")'.
library(knitr) # to print the tables within notebook
library(foreach) #run parallel loops
Attaching package: ‘foreach’
The following object is masked from ‘package:DescTools’:
%:%
library(parallel)
library(doParallel) #run parallel loops
Loading required package: iterators
library(ggpubr) # emmeans
library(mediation) #mediation analysis
Loading required package: MASS
Attaching package: ‘MASS’
The following object is masked from ‘package:dplyr’:
select
Loading required package: mvtnorm
Loading required package: sandwich
mediation: Causal Mediation Analysis
Version: 4.5.0
Attaching package: ‘mediation’
The following object is masked from ‘package:psych’:
mediate
library(plotly) #for interactive plots
Attaching package: ‘plotly’
The following object is masked from ‘package:MASS’:
select
The following object is masked from ‘package:ggplot2’:
last_plot
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
library(jtools) #for theme_apa
Attaching package: ‘jtools’
The following object is masked from ‘package:DescTools’:
%nin%
library(JSmediation) #moderated mediation
library(wesanderson)
source("functions.R")
Data
Here we load in our data and preprocess it in steps. We first need to separate the different surveys that were delivered to bring them into the same sampling times, merge in some descriptives we need as covariates, and estimate subject-centered and lagged variables for our models later.
- Load and clean data
# Load the data
MEDAL_ESM_compleet <- read_excel("data/MEDAL_ESM_compleet.xlsx")
# Move variables around and clean names
MEDAL_ESM_compleet= MEDAL_ESM_compleet %>%
rename(id='Movisens-ID') %>%
clean_names() %>%
rename(subjectcode = 'deelnemersnr') %>%
relocate('subjectcode', .after = 'id')
df_medal_try = MEDAL_ESM_compleet
- Split different EMA surveys we have
# Sleep EMA Qs
df_medal_sleep = df_medal_try %>%
filter(form=='Slaap') %>%
dplyr::select(c(1, 2, 4, 5, 7, 9, 14))
# Recent EMA Qs
df_medal_recent = df_medal_try %>%
filter(form=='Recent') %>%
dplyr::select(c(1, 2, 4, 5, 7, 9, contains('rec')))
# Remote EMA Qs
df_medal_remote = df_medal_try %>%
filter(form=='Remote') %>%
dplyr::select(c(1, 2, 4, 5, 7, 9, contains('rem')))
# Mastery EMA Qs
df_medal_mastery = df_medal_try %>%
filter(form=='Mastery') %>%
dplyr::select(c(1, 2, 4, 5, 7, 9, contains('master')))
# Standard Qs
df_medal_standard = df_medal_try %>%
filter(form=='Standaard') %>%
dplyr::select(c(1, 2, 4, 5, 7, 9, (-contains('mastery') & -contains('rem') & -contains('rec')))) %>%
dplyr::select(-c(7,13,14))
# merge sleep and standard
df_medal_merged = merge(df_medal_sleep, df_medal_standard, by=c('id', 'trigger_counter', 'subjectcode'), suffixes = c("_sleep", ""), all=T )
# merge to recent, remote and mastery
df_medal_merged= merge(df_medal_merged, df_medal_recent, by=c('id', 'trigger_counter', 'subjectcode' ), suffixes = c('', '_recent'), all = T )
df_medal_merged = merge(df_medal_merged, df_medal_remote, by=c('id', 'trigger_counter', 'subjectcode' ), suffixes = c('', '_remote'), all = T )
df_medal_merged = merge(df_medal_merged, df_medal_mastery, by=c('id', 'trigger_counter', 'subjectcode' ), suffixes = c('', '_mastery'), all = T )
# Fix start dates and times
df_medal_merged$form_start_date <- as.character(df_medal_merged$form_start_date)
df_medal_merged$form_start_date <- as.ITime(df_medal_merged$form_start_date)
df_medal_merged = df_medal_merged %>%
dplyr::mutate(form_start_date = ifelse(is.na(form_start_date), form_start_date_sleep, form_start_date))
- Add variables on Education, Gender, and Age
# Load in previous data for demographics (also contains EMA)
load("data/IPAQ_Maeve_Workspace.RData")
df_MEDAL <- df_MEDAL[-c(192), ]
# Select relevant demo info
df_MEDAL = df_MEDAL %>%
dplyr::select(1, 3, 5:7) %>%
rename('subjectcode' = 'subject', 'education' = 'Education3groups', 'n_episodes'='NumberEpisodes' )
# merge demo to full EMA
df_medal_merged = merge(df_medal_merged, df_MEDAL, by = c('subjectcode'), all = T ) %>%
clean_names()
df_medal_merged$education = as.factor(df_medal_merged$education)
df_medal_merged$gender = as.factor(df_medal_merged$gender)
df_medal_merged = df_medal_merged %>%
relocate(c('id', 'gender', 'age', 'education'), .after = 'subjectcode') %>%
relocate ('age', .after = 'gender') %>%
relocate ('education', .after = 'age') %>%
relocate ('id', .before = 'subjectcode')
- Categorize the subjectcode into the three conditions (Depressed, Remitted, Control (Never-depressed))
df_medal_merged$condition = case_when(df_medal_merged$subjectcode >= 700 & df_medal_merged$subjectcode < 800 ~ "remitted",
df_medal_merged$subjectcode >= 800 & df_medal_merged$subjectcode < 900 ~ "depressed",
df_medal_merged$subjectcode >= 900 ~ "control")
df_medal_merged = df_medal_merged %>% relocate ('condition', .after = 'subjectcode' )
df_medal_merged$condition <- as.factor(df_medal_merged$condition)
- Calculate reaction time
df_medal_merged$rt_sleep = lubridate::as.difftime( df_medal_merged$form_finish_date_sleep - df_medal_merged$form_start_date_sleep)
- Separate time from when trigger was sent
df_medal_merged = df_medal_merged %>%
tidyr::separate(trigger, c('Random', 'Time', 'Trigger_Time_1', 'Trigger_Time_2')) %>%
dplyr::mutate(trigger_time = paste(Trigger_Time_1, Trigger_Time_2, sep=':')) %>%#separate time from previous trigger
dplyr::mutate(trigger = paste(Random, Time, trigger_time, sep=' ')) #bring back 'trigger' column
#Turn numbers into time format
df_medal_merged$trigger_time <- as.ITime(df_medal_merged$trigger_time)
- Find the trigger number per day
#df_medal_merged$trigger_counter[is.na(df_medal_merged$trigger_time)] <- 1
df_medal_merged$trigger_number[is.na(df_medal_merged$trigger_time)] <- 1
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("10:00:00"))& df_medal_merged$trigger_time < (as.ITime("12:00:00"))] <- 2
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("12:00:00"))& df_medal_merged$trigger_time < (as.ITime("14:00:00"))] <- 3
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("14:00:00"))& df_medal_merged$trigger_time < (as.ITime("16:00:00"))] <- 4
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("16:00:00"))& df_medal_merged$trigger_time < (as.ITime("18:00:00"))] <- 5
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("18:00:00"))& df_medal_merged$trigger_time < (as.ITime("20:00:00"))] <- 6
df_medal_merged$trigger_number[df_medal_merged$trigger_time >= (as.ITime("20:00:00"))& df_medal_merged$trigger_time < (as.ITime("23:00:01"))] <- 7
# df
df_medal_merged = df_medal_merged %>%
relocate ('trigger_number', .after = 'trigger_counter')%>% relocate('trigger_time', .before ='form_start_date') %>%
relocate('trigger', .before ='trigger_time')
- Final cleaning of the dataset
#Create dataset where double morning list is removed
df_medal_merged = df_medal_merged %>%
dplyr::mutate(trigger_counter=ifelse(trigger_number==1 & lag(trigger_number)==1, lag(trigger_counter), trigger_counter)) %>%
dplyr::mutate(trigger_counter=ifelse(trigger_number==1 & lag(trigger_number)==1, lag(trigger_counter), trigger_counter)) %>%
dplyr::mutate(trigger_counter=ifelse(trigger_number==1 & lag(trigger_number)==1, lag(trigger_counter), trigger_counter)) %>%
dplyr::mutate(trigger_counter=ifelse(trigger_number==1 & lag(trigger_number)==1, lag(trigger_counter), trigger_counter)) %>%
dplyr::mutate(trigger_counter=ifelse(trigger_number==1 & lag(trigger_number)==1, lag(trigger_counter), trigger_counter))
# now we have the clean dataframe, remove duplicated coloumns
df_medal_clean = df_medal_merged %>%
dplyr::group_by(subjectcode) %>%
distinct(trigger_counter, .keep_all = TRUE) %>%
dplyr::select (1:12, 17:60) %>%
dplyr::mutate(original_order = row_number()) %>%
relocate('original_order', .before = 'id')
#Set the order of the factor to control, remission, depression (for visual purposes)
df_medal_clean$condition <- factor(df_medal_clean$condition, levels=c('control', 'remitted', 'depressed' ), labels=c('control', 'remitted', 'depressed'))
# Create dummy variable
df_medal_clean = df_medal_clean %>%
mutate(condition_dummy = case_when(condition == 'depressed'~ 3, condition == 'remitted'~ 2, condition == 'control' ~ 1))
df_medal_clean$condition_dummy = as.factor(df_medal_clean$condition_dummy)
#set weekday
df_medal_clean$form_finish_date <- as.character(df_medal_clean$form_finish_date)
df_medal_clean$form_finish_date <- strptime(df_medal_clean$form_finish_date, format = '%Y-%m-%d %H:%M:%S')
df_medal_clean$finish_date <- as.Date(df_medal_clean$form_finish_date)
df_medal_clean$weekday <- as.integer(format(df_medal_clean$finish_date, '%w'))
df_medal_clean = df_medal_clean %>% relocate('weekday', .after = 'trigger_number')
#solve duplicate issue
df_medal_duplicate = df_medal_clean %>% dplyr::group_by(subjectcode, weekday) %>% filter(duplicated(trigger_number))
#since row 10 for subject 712 is a duplicate morning list
df_medal_clean <- subset(df_medal_clean, !(subjectcode == 712 & original_order == 10))
df_medal_clean = df_medal_clean %>% dplyr::group_by(subjectcode, weekday) %>%
mutate(temp = lead(trigger_number),
trigger_number = case_when(trigger_number == temp ~ (temp -1), TRUE ~ trigger_number)) %>%
select(-temp)
#Take the rows out that have 'NA'for the weekday since form wasn't finished and there is no data for PA, NA, or Memory
df_medal_clean = df_medal_clean %>% filter(!is.na(weekday))
df_medal_clean$original_order <- 1:nrow(df_medal_clean)
# Create expanded df with all potential datapoints
df_medal_day = df_medal_clean %>%
dplyr::select('subjectcode', 'weekday', 'original_order') %>%
dplyr::mutate(weekday = as.numeric(weekday)) %>%
dplyr::group_by(subjectcode) %>%
dplyr:: distinct(weekday, .keep_all =T) %>%
dplyr::ungroup()
df_medal_day = df_medal_day %>%
slice(rep(1:n(), each = 7)) %>%
dplyr::mutate(trigger_number = rep(1:7, length.out=n())) %>%
dplyr::rename(order = original_order)
#merge with main dataframe
df_medal_clean = merge(df_medal_day, df_medal_clean, by=c('subjectcode', 'trigger_number', 'weekday'), all= T)
df_medal_clean = df_medal_clean %>% mutate(order = as.numeric(order))
df_medal_clean = arrange(df_medal_clean, order)
- Centre, scale, and average Variables
used_vars = c("neg_mood", "rec_mem_neg_mood", "rem_mem_neg_mood", "pos_mood", "rec_mem_pos_mood", "rem_mem_pos_mood")
#Centering & scaling
df_medal_clean = df_medal_clean %>%
dplyr::group_by(subjectcode) %>%
# Center and scale
dplyr::mutate( across(used_vars, ~ (.x/10), .names = "{.col}" ),
across(used_vars, ~ mean(.x, na.rm=T), .names = "{.col}_m" ),
across(used_vars, ~ (.x - mean(.x, na.rm=T)), .names = "{.col}_c" ),
across(paste0(used_vars, "_c"), ~ DescTools::Winsorize(.x, na.rm = T), .names = "{.col}")) %>%
ungroup() %>%
# Rescale to positive
mutate(across(c(paste0(used_vars,"_c")), ~ abs(min(.x, na.rm = T)) + 1 + .x, .names = "{.col}s"))
- Lag variables
# Remote
df_medal_clean = df_medal_clean %>%
dplyr::group_by(subjectcode) %>%
mutate(rem_mem_pos_mood_lag = lead(rem_mem_pos_mood, n=7, order_by=subjectcode),
rem_mem_neg_mood_lag = lead(rem_mem_neg_mood, n=7, order_by=subjectcode),
pos_mood_lag_rem = lead(pos_mood, n=7, order_by=subjectcode),
neg_mood_lag_rem = lead(neg_mood, n=7, order_by=subjectcode),
rem_mem_pos_mood_cs_lag = lead(rem_mem_pos_mood_cs, n=7, order_by=subjectcode),
rem_mem_neg_mood_cs_lag = lead(rem_mem_neg_mood_cs, n=7, order_by=subjectcode),
pos_mood_cs_lag_rem = lead(pos_mood_cs, n=7, order_by=subjectcode),
neg_mood_cs_lag_rem = lead(neg_mood_cs, n=7, order_by=subjectcode),
rem_mem_pos_mood_c_lag = lead(rem_mem_pos_mood_c, n=7, order_by=subjectcode),
rem_mem_neg_mood_c_lag = lead(rem_mem_neg_mood_c, n=7, order_by=subjectcode),
pos_mood_c_lag_rem = lead(pos_mood_c, n=7, order_by=subjectcode),
neg_mood_c_lag_rem = lead(neg_mood_c, n=7, order_by=subjectcode)) %>%
filter(!is.na(original_order)) # filter out the NA rows for the lagging of recent memory
# Recent
df_medal_clean = df_medal_clean %>%
dplyr::group_by(subjectcode) %>%
mutate(rec_mem_pos_mood_lag = lead(rec_mem_pos_mood, n=1, order_by=subjectcode),
rec_mem_neg_mood_lag = lead(rec_mem_neg_mood, n=1, order_by=subjectcode),
pos_mood_lag_rec = lead(pos_mood, n=1, order_by=subjectcode),
neg_mood_lag_rec = lead(neg_mood, n=1, order_by=subjectcode),
rec_mem_pos_mood_cs_lag = lead(rec_mem_pos_mood_cs, n=1, order_by=subjectcode),
rec_mem_neg_mood_cs_lag = lead(rec_mem_neg_mood_cs, n=1, order_by=subjectcode),
pos_mood_cs_lag_rec = lead(pos_mood_cs, n=1, order_by=subjectcode),
neg_mood_cs_lag_rec = lead(neg_mood_cs, n=1, order_by=subjectcode),
rec_mem_pos_mood_c_lag = lead(rec_mem_pos_mood_c, n=1, order_by=subjectcode),
rec_mem_neg_mood_c_lag = lead(rec_mem_neg_mood_c, n=1, order_by=subjectcode),
pos_mood_c_lag_rec = lead(pos_mood_c, n=1, order_by=subjectcode),
neg_mood_c_lag_rec = lead(neg_mood_c, n=1, order_by=subjectcode)) %>%
ungroup()
Main Effects
A simple linear regression analysis was done to look at the differences in positive and negative mood ratings per condition.
Linear Mixed Models for PA and NA
#positive mood
positive_model = lmer(pos_mood ~ condition + (1|subjectcode), data = df_medal_clean)
#negative mood
negative_model = lmer(neg_mood ~ condition + (1|subjectcode), data = df_medal_clean)
asis_output(tab_model (positive_model, negative_model,
show.se = T, show.df = T, show.aic = T, transform = NULL,
show.stat = T, show.std = T,
title = 'Condition Differences Mood Rating', dv.labels = c('PA Scaled', 'NA Scaled') )$knitr)
Condition Differences Mood Rating
|
|
PA Scaled
|
NA Scaled
|
|
Predictors
|
Estimates
|
std. Error
|
std. Beta
|
standardized std. Error
|
CI
|
standardized CI
|
Statistic
|
p
|
df
|
Estimates
|
std. Error
|
std. Beta
|
standardized std. Error
|
CI
|
standardized CI
|
Statistic
|
p
|
df
|
|
(Intercept)
|
7.49
|
0.17
|
0.56
|
0.08
|
7.15 – 7.83
|
0.40 – 0.71
|
43.56
|
<0.001
|
7365.00
|
1.14
|
0.20
|
-0.63
|
0.08
|
0.74 – 1.53
|
-0.79 – -0.47
|
5.65
|
<0.001
|
7361.00
|
|
condition [remitted]
|
-1.10
|
0.22
|
-0.50
|
0.10
|
-1.53 – -0.67
|
-0.70 – -0.31
|
-5.04
|
<0.001
|
7365.00
|
1.42
|
0.26
|
0.58
|
0.10
|
0.92 – 1.93
|
0.37 – 0.78
|
5.53
|
<0.001
|
7361.00
|
|
condition [depressed]
|
-2.90
|
0.25
|
-1.32
|
0.12
|
-3.40 – -2.40
|
-1.55 – -1.10
|
-11.40
|
<0.001
|
7365.00
|
3.68
|
0.30
|
1.49
|
0.12
|
3.10 – 4.27
|
1.26 – 1.73
|
12.32
|
<0.001
|
7361.00
|
|
Random Effects
|
|
σ2
|
2.12
|
2.12
|
|
τ00
|
1.57 subjectcode
|
2.18 subjectcode
|
|
ICC
|
0.43
|
0.51
|
|
N
|
189 subjectcode
|
189 subjectcode
|
|
Observations
|
7370
|
7366
|
|
Marginal R2 / Conditional R2
|
0.234 / 0.560
|
0.296 / 0.653
|
|
AIC
|
27097.145
|
27153.068
|
Plot
#create boxplot for negative and positive affect for each group with significance levels
combine_data = df_medal_clean %>%
tidyr::pivot_longer(cols=c(pos_mood, neg_mood), names_to = 'mood_type', values_to = 'mood_rating') %>%
dplyr::mutate(mood_type = factor(mood_type, levels = c('pos_mood' , 'neg_mood')))
# Plot
lm_plot = ggplot(combine_data, aes(x=condition, y = mood_rating, fill= condition)) +
geom_boxplot() +
labs(x ='Group', y ='Mood (scaled units)' ) +
scale_x_discrete(labels = c('control' = 'Never Depressed', 'remitted' = 'Remitted', 'depressed' = 'Depressed' )) +
facet_wrap( ~ mood_type, ncol =3, nrow = 2, labeller = labeller(mood_type = c('pos_mood' = 'Positive Mood', 'neg_mood' = 'Negative Mood'))) +
geom_signif(comparisons = list(c('control', 'remitted'), c('control' , 'depressed'), c('remitted' , 'depressed' )), map_signif_level = T, y_position = c(15, 13, 11)) +
scale_fill_manual(values = wesanderson::wes_palette(n=3, name='GrandBudapest2' )) +
theme_apa() +
guides(fill=F)
ggplotly(lm_plot)
ggsave('figure_1_main_effects.pdf', dpi = 320, width = 12, height = 8, path = "figures/")

Follow-Up
emmeans::emmeans(positive_model, pairwise ~ condition, pbkrtest.limit = 7800, lmerTest.limit=7800)
$emmeans
condition emmean SE df lower.CL upper.CL
control 7.49 0.172 186 7.15 7.83
remitted 6.39 0.136 186 6.12 6.65
depressed 4.59 0.188 186 4.21 4.96
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
$contrasts
contrast estimate SE df t.ratio p.value
control - remitted 1.1 0.219 186 5.038 <.0001
control - depressed 2.9 0.255 186 11.400 <.0001
remitted - depressed 1.8 0.232 186 7.760 <.0001
Degrees-of-freedom method: kenward-roger
P value adjustment: tukey method for comparing a family of 3 estimates
emmeans::emmeans(negative_model, pairwise ~ condition, pbkrtest.limit = 7800, lmerTest.limit=7800)
$emmeans
condition emmean SE df lower.CL upper.CL
control 1.14 0.202 186 0.741 1.54
remitted 2.56 0.159 186 2.247 2.88
depressed 4.82 0.221 186 4.388 5.26
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
$contrasts
contrast estimate SE df t.ratio p.value
control - remitted -1.42 0.257 186 -5.530 <.0001
control - depressed -3.68 0.299 186 -12.322 <.0001
remitted - depressed -2.26 0.272 186 -8.309 <.0001
Degrees-of-freedom method: kenward-roger
P value adjustment: tukey method for comparing a family of 3 estimates
Exploratory Analyses
Moderated Mediation
RemPA-CurrPA
df_medal_moderation = df_medal_clean_remote %>%
filter(!(is.na(pos_mood) | is.na(rem_mem_pos_mood_lag)))
#mediation first
med_fit_h2_pos_rem <- lme4::lmer(rem_mem_pos_mood_lag ~ condition_dummy +
age + gender + education +
(1 |subjectcode),
data =df_medal_moderation)
# full model
out_fit_h2_pos_rem <-lme4::lmer(pos_mood ~ condition_dummy + rem_mem_pos_mood_lag
+ age + gender +education +
(1 + rem_mem_pos_mood_lag |subjectcode),
data=df_medal_moderation)
Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
Model failed to converge with max|grad| = 0.00602257 (tol = 0.002, component 1)
#mediation analysis for control and remitted
med_pos_rem_rem <- mediation::mediate(med_fit_h2_pos_rem, out_fit_h2_pos_rem,
treat = 'condition_dummy' , control.value = 1, treat.value = 2 , mediator = 'rem_mem_pos_mood_lag')
summary(med_pos_rem_rem)
Causal Mediation Analysis
Quasi-Bayesian Confidence Intervals
Mediator Groups: subjectcode
Outcome Groups: subjectcode
Output Based on Overall Averages Across Groups
Estimate 95% CI Lower 95% CI Upper p-value
ACME (control) -0.662 -0.975 -0.35 <2e-16 ***
ACME (treated) -0.662 -0.975 -0.35 <2e-16 ***
ADE (control) -0.370 -0.702 -0.04 0.028 *
ADE (treated) -0.370 -0.702 -0.04 0.028 *
Total Effect -1.031 -1.464 -0.57 <2e-16 ***
Prop. Mediated (control) 0.641 0.417 0.95 <2e-16 ***
Prop. Mediated (treated) 0.641 0.417 0.95 <2e-16 ***
ACME (average) -0.662 -0.975 -0.35 <2e-16 ***
ADE (average) -0.370 -0.702 -0.04 0.028 *
Prop. Mediated (average) 0.641 0.417 0.95 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Sample Size Used: 771
Simulations: 1000
#create new dataframes with only control remitted and only control depressed
df_medal_con_rem = df_medal_clean %>% filter(condition=='control' | condition == 'remitted')
df_medal_con_dep = df_medal_clean %>% filter(condition=='control' | condition == 'depressed')
#remitted group
df_medal_con_rem$condition_dummy = build_contrast(df_medal_con_rem$condition, 'control', 'remitted')
med_h2_pos_rem_rem <- mdt_moderated(data = df_medal_con_rem, IV =condition_dummy, DV = pos_mood, M = rem_mem_pos_mood_lag, Mod = pos_mood_lag_rem)
rbindlist(med_h2_pos_rem_rem$paths, idcol = T)
NA
RemNA - CurrNA
df_medal_moderation = df_medal_clean_remote %>% filter(!(is.na(neg_mood) | is.na(rem_mem_neg_mood_lag)))
#mediation first
med_fit_h2_neg_rem <- lme4::lmer(rem_mem_neg_mood_lag ~ condition_dummy +
age + gender + education +
(1 |subjectcode),
control = lmerControl(calc.derivs = F, optimizer='bobyqa', optCtrl=list(maxfun=1e6)),
data =df_medal_moderation)
out_fit_h2_neg_rem <-lme4::lmer(neg_mood ~ condition_dummy + rem_mem_neg_mood_lag +
age + gender + education +
(1 + rem_mem_neg_mood_lag |subjectcode),
control = lmerControl(calc.derivs = F, optimizer='bobyqa', optCtrl=list(maxfun=1e6)),
data=df_medal_moderation)
#mediation analysis for control and depressed
med_neg_rem_dep <- mediation::mediate(med_fit_h2_neg_rem, out_fit_h2_neg_rem,
mediator = 'rem_mem_neg_mood_lag', treat = 'condition_dummy' ,
control.value = 1, treat.value = 3 , sims=10000)
summary(med_neg_rem_dep)
Causal Mediation Analysis
Quasi-Bayesian Confidence Intervals
Mediator Groups: subjectcode
Outcome Groups: subjectcode
Output Based on Overall Averages Across Groups
Estimate 95% CI Lower 95% CI Upper p-value
ACME (control) 2.346 1.866 2.86 <2e-16 ***
ACME (treated) 2.346 1.866 2.86 <2e-16 ***
ADE (control) 1.227 0.784 1.67 <2e-16 ***
ADE (treated) 1.227 0.784 1.67 <2e-16 ***
Total Effect 3.573 2.996 4.16 <2e-16 ***
Prop. Mediated (control) 0.657 0.555 0.76 <2e-16 ***
Prop. Mediated (treated) 0.657 0.555 0.76 <2e-16 ***
ACME (average) 2.346 1.866 2.86 <2e-16 ***
ADE (average) 1.227 0.784 1.67 <2e-16 ***
Prop. Mediated (average) 0.657 0.555 0.76 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Sample Size Used: 770
Simulations: 10000
#mediation analysis for control and remitted
med_neg_rem_rem <- mediation::mediate(med_fit_h2_neg_rem, out_fit_h2_neg_rem, treat = 'condition_dummy' , control.value = 1, treat.value = 2 , mediator = 'rem_mem_neg_mood_lag', sims=10000)
summary(med_neg_rem_rem)
Causal Mediation Analysis
Quasi-Bayesian Confidence Intervals
Mediator Groups: subjectcode
Outcome Groups: subjectcode
Output Based on Overall Averages Across Groups
Estimate 95% CI Lower 95% CI Upper p-value
ACME (control) 0.894 0.546 1.26 <2e-16 ***
ACME (treated) 0.894 0.546 1.26 <2e-16 ***
ADE (control) 0.422 0.142 0.70 0.0036 **
ADE (treated) 0.422 0.142 0.70 0.0036 **
Total Effect 1.315 0.874 1.76 <2e-16 ***
Prop. Mediated (control) 0.679 0.503 0.87 <2e-16 ***
Prop. Mediated (treated) 0.679 0.503 0.87 <2e-16 ***
ACME (average) 0.894 0.546 1.26 <2e-16 ***
ADE (average) 0.422 0.142 0.70 0.0036 **
Prop. Mediated (average) 0.679 0.503 0.87 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Sample Size Used: 770
Simulations: 10000
#create new dataframes with only control remitted and only control depressed
df_medal_con_rem = df_medal_clean %>% filter(condition=='control' | condition == 'remitted')
df_medal_con_dep = df_medal_clean %>% filter(condition=='control' | condition == 'depressed')
#remitted group
df_medal_con_rem$condition_dummy = build_contrast(df_medal_con_rem$condition, 'control', 'remitted')
med_h2_neg_rem_rem <- mdt_moderated(data = df_medal_con_rem, IV = condition_dummy, DV = neg_mood, M = rem_mem_neg_mood_lag, Mod = neg_mood_lag_rem)
rbindlist(med_h2_neg_rem_rem$paths, idcol = T)
#depressed group
df_medal_con_dep$condition_dummy = build_contrast(df_medal_con_dep$condition, 'control', 'depressed')
med_h2_neg_rem_dep <- mdt_moderated(data = df_medal_con_dep, IV = condition_dummy, DV = neg_mood, M = rem_mem_neg_mood_lag, Mod = neg_mood_lag_rem)
rbindlist(med_h2_neg_rem_dep$paths,idcol = T)
NA
Context
asis_output(tab_model( (lmer(pos_mood_cs ~ rec_mem_pos_mood_cs_lag*context_location + (1 | subjectcode), data = df_medal_clean)),
(lmer(pos_mood_cs ~ rem_mem_pos_mood_cs_lag*context_location + (1 | subjectcode), data = df_medal_clean)),
(lmer(neg_mood_cs ~ rem_mem_neg_mood_cs_lag*context_location + (1 | subjectcode), data = df_medal_clean)),
(lmer(neg_mood_cs ~ rem_mem_neg_mood_cs_lag*context_location + (1 | subjectcode), data = df_medal_clean)))$knitr)
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
|
|
pos mood cs
|
pos mood cs
|
neg mood cs
|
neg mood cs
|
|
Predictors
|
Estimates
|
CI
|
p
|
Estimates
|
CI
|
p
|
Estimates
|
CI
|
p
|
Estimates
|
CI
|
p
|
|
(Intercept)
|
3.81
|
3.46 – 4.16
|
<0.001
|
5.35
|
4.64 – 6.05
|
<0.001
|
4.77
|
4.11 – 5.44
|
<0.001
|
4.77
|
4.11 – 5.44
|
<0.001
|
|
rec mem pos mood cs lag
|
0.49
|
0.44 – 0.54
|
<0.001
|
|
|
|
|
|
|
|
|
|
|
context location
|
0.01
|
-0.13 – 0.14
|
0.936
|
-0.25
|
-0.53 – 0.02
|
0.068
|
-0.19
|
-0.44 – 0.06
|
0.136
|
-0.19
|
-0.44 – 0.06
|
0.136
|
rec mem pos mood cs lag * context location
|
0.01
|
-0.01 – 0.03
|
0.521
|
|
|
|
|
|
|
|
|
|
|
rem mem pos mood cs lag
|
|
|
|
0.33
|
0.21 – 0.45
|
<0.001
|
|
|
|
|
|
|
rem mem pos mood cs lag * context location
|
|
|
|
0.05
|
0.01 – 0.10
|
0.023
|
|
|
|
|
|
|
|
rem mem neg mood cs lag
|
|
|
|
|
|
|
0.26
|
0.14 – 0.39
|
<0.001
|
0.26
|
0.14 – 0.39
|
<0.001
|
rem mem neg mood cs lag * context location
|
|
|
|
|
|
|
0.04
|
-0.01 – 0.08
|
0.129
|
0.04
|
-0.01 – 0.08
|
0.129
|
|
Random Effects
|
|
σ2
|
1.28
|
1.48
|
1.45
|
1.45
|
|
τ00
|
0.00 subjectcode
|
0.00 subjectcode
|
0.00 subjectcode
|
0.00 subjectcode
|
|
N
|
189 subjectcode
|
188 subjectcode
|
188 subjectcode
|
188 subjectcode
|
|
Observations
|
3140
|
789
|
789
|
789
|
|
Marginal R2 / Conditional R2
|
0.257 / NA
|
0.163 / NA
|
0.100 / NA
|
0.100 / NA
|
SRET
In addition to the EMA, participants also completed the SRET. This is a lab based memory bias measure. We want to check whether our memory bias measures from real-life are linked to ones from the lab in this supplementary analysis.
library('haven')
Warning: package ‘haven’ was built under R version 4.1.3
sret_file = file.path("Z:/", "inbox", "transfer-2023-12-07-02-15-pm", 'MEDAL_pre and post quest and remote recall_workfile!!_for paper only var.sav')
sret_data = read_sav(sret_file)
sret_data = sret_data %>% select(c(1,4)) %>% distinct()
df_medal_rec_cor1 = df_medal_clean %>%
dplyr::select(subjectcode, pos_mood, rec_mem_pos_mood_lag) %>%
na.omit() %>%
dplyr::group_by(subjectcode) %>%
dplyr::mutate(corr = tryCatch(cor(rec_mem_pos_mood_lag, pos_mood), warning = function(e) NA),
model_type = "PA_REC") %>%
dplyr::select(subjectcode, corr, model_type) %>%
dplyr::distinct() %>% ungroup()
df_medal_rec_cor2 = df_medal_clean %>%
dplyr::select(subjectcode, neg_mood, rec_mem_neg_mood_lag) %>%
na.omit() %>%
dplyr::group_by(subjectcode) %>%
dplyr::mutate(corr = tryCatch(cor(rec_mem_neg_mood_lag, neg_mood), warning = function(e) NA),
model_type = "NA_REC") %>%
dplyr::select(subjectcode, corr, model_type) %>%
dplyr::distinct() %>% ungroup()
df_medal_rem_cor1 = df_medal_clean %>%
dplyr::select(subjectcode, pos_mood, rem_mem_pos_mood_lag) %>%
na.omit() %>%
dplyr::group_by(subjectcode) %>%
dplyr::mutate(corr = tryCatch(cor(rem_mem_pos_mood_lag, pos_mood), warning = function(e) NA),
model_type = "PA_REM") %>%
dplyr::select(subjectcode, corr, model_type) %>%
dplyr::distinct()
df_medal_rem_cor2 = df_medal_clean %>%
dplyr::select(subjectcode, neg_mood, rem_mem_neg_mood_lag) %>%
na.omit() %>%
dplyr::group_by(subjectcode) %>%
dplyr::mutate(corr = tryCatch(cor(rem_mem_neg_mood_lag, neg_mood), warning = function(e) NA),
model_type = "NA_REM") %>%
dplyr::select(subjectcode, corr, model_type) %>%
dplyr::distinct()
df_cors = rbindlist(list(df_medal_rec_cor1, df_medal_rec_cor2, df_medal_rem_cor1, df_medal_rem_cor2))
df_ref = merge(sret_data, df_cors, by.x = 'subject', by.y = 'subjectcode')
df_ref = df_ref %>% rename(SRET = SRET_BiasGotlib_neg) %>% dplyr::mutate(group = ifelse(subject<800, "remitted",
ifelse(subject>=900, "control", 'depressed')) )
for (mod_type in c("PA_REC", "PA_REM", "NA_REC", "NA_REM")){
print(mod_type)
print(summary(lm(SRET ~ corr*group, data = df_ref %>% filter(model_type == mod_type))))
}
[1] "PA_REC"
Call:
lm(formula = SRET ~ corr * group, data = df_ref %>% filter(model_type ==
mod_type))
Residuals:
Min 1Q Median 3Q Max
-0.42802 -0.18783 -0.03731 0.07877 0.96612
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.032066 0.055434 0.578 0.5637
corr 0.009979 0.109528 0.091 0.9275
groupdepressed 0.207749 0.113678 1.828 0.0694 .
groupremitted 0.109699 0.078769 1.393 0.1655
corr:groupdepressed 0.299086 0.203331 1.471 0.1431
corr:groupremitted 0.145614 0.151633 0.960 0.3383
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2605 on 171 degrees of freedom
(12 observations deleted due to missingness)
Multiple R-squared: 0.2304, Adjusted R-squared: 0.2079
F-statistic: 10.24 on 5 and 171 DF, p-value: 1.343e-08
[1] "PA_REM"
Call:
lm(formula = SRET ~ corr * group, data = df_ref %>% filter(model_type ==
mod_type))
Residuals:
Min 1Q Median 3Q Max
-0.41550 -0.21434 -0.03978 0.12018 0.96298
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.034360 0.044794 0.767 0.444147
corr 0.008142 0.065661 0.124 0.901462
groupdepressed 0.365632 0.065231 5.605 8.57e-08 ***
groupremitted 0.192437 0.056284 3.419 0.000792 ***
corr:groupdepressed 0.007906 0.096231 0.082 0.934621
corr:groupremitted -0.025126 0.082845 -0.303 0.762047
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2675 on 165 degrees of freedom
(17 observations deleted due to missingness)
Multiple R-squared: 0.2043, Adjusted R-squared: 0.1802
F-statistic: 8.475 on 5 and 165 DF, p-value: 3.685e-07
[1] "NA_REC"
Call:
lm(formula = SRET ~ corr * group, data = df_ref %>% filter(model_type ==
mod_type))
Residuals:
Min 1Q Median 3Q Max
-0.45379 -0.17704 -0.03939 0.08131 0.96345
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.03215 0.04477 0.718 0.473691
corr 0.01727 0.10065 0.172 0.863976
groupdepressed 0.29548 0.08311 3.555 0.000489 ***
groupremitted 0.10471 0.06401 1.636 0.103709
corr:groupdepressed 0.14637 0.15930 0.919 0.359496
corr:groupremitted 0.18205 0.13735 1.325 0.186793
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2605 on 170 degrees of freedom
(13 observations deleted due to missingness)
Multiple R-squared: 0.2323, Adjusted R-squared: 0.2097
F-statistic: 10.29 on 5 and 170 DF, p-value: 1.249e-08
[1] "NA_REM"
Call:
lm(formula = SRET ~ corr * group, data = df_ref %>% filter(model_type ==
mod_type))
Residuals:
Min 1Q Median 3Q Max
-0.43367 -0.17164 -0.04881 0.12752 0.94467
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.04423 0.04128 1.071 0.285714
corr -0.02001 0.06467 -0.309 0.757395
groupdepressed 0.34096 0.06427 5.305 3.86e-07 ***
groupremitted 0.19828 0.05408 3.667 0.000338 ***
corr:groupdepressed 0.08919 0.10774 0.828 0.409041
corr:groupremitted -0.07917 0.08544 -0.927 0.355620
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2702 on 154 degrees of freedom
(28 observations deleted due to missingness)
Multiple R-squared: 0.2103, Adjusted R-squared: 0.1846
F-statistic: 8.201 on 5 and 154 DF, p-value: 6.88e-07
Relative Bias
Here we want to check for the relative NA/PA bias. So we extact the random effects from the models to get the slopes for each subject, and then compare the NA/PA slopes. This tells us if theres a bias between negative and positive memory.
# Get individual slopes
pos_rec_ref = as.data.frame(ranef(h1_pos_recent_models[[2]])) %>% filter(term!='(Intercept)') %>% select(c(3:5))
pos_rem_ref = as.data.frame(ranef(h1_pos_remote_models[[2]])) %>% filter(term!='(Intercept)') %>% select(c(3:5))
neg_rec_ref = as.data.frame(ranef(h1_neg_recent_models[[4]])) %>% filter(term!='(Intercept)') %>% select(c(3:5))
neg_rem_ref = as.data.frame(ranef(h1_neg_remote_models[[4]])) %>% filter(term!='(Intercept)') %>% select(c(3:5))
pos_rec_ref$mod = "PA_REC"
pos_rem_ref$mod = "PA_REM"
neg_rec_ref$mod = "NA_REC"
neg_rem_ref$mod = "NA_REM"
# Put together into a new data frame
df_ref = rbindlist(list(pos_rec_ref, pos_rem_ref, neg_rec_ref, neg_rem_ref))
df_ref = df_ref %>%
dplyr::mutate(sub = as.numeric(as.character(grp))) %>%
dplyr::mutate(group = ifelse(sub <= 800, "remitted",
ifelse(sub>=900, "control", 'depressed')) )
df_ref_rec = df_ref %>% filter(mod == 'PA_REC' | mod=='NA_REC')
df_ref_rem = df_ref %>% filter(mod == 'PA_REM' | mod=='NA_REM')
summary(lmer(condsd ~ mod*group + (1|sub), data = df_ref_rec))
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: condsd ~ mod * group + (1 | sub)
Data: df_ref_rec
REML criterion at convergence: -1627.3
Scaled residuals:
Min 1Q Median 3Q Max
-5.2098 -0.1327 0.0031 0.2809 2.0044
Random effects:
Groups Name Variance Std.Dev.
sub (Intercept) 7.518e-05 0.008671
Residual 5.555e-04 0.023568
Number of obs: 370, groups: sub, 185
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 0.174568 0.003449 358.899624 50.607 < 2e-16 ***
modPA_REC -0.151833 0.004578 182.000000 -33.164 < 2e-16 ***
groupdepressed -0.031248 0.005060 358.899624 -6.175 1.79e-09 ***
groupremitted -0.019827 0.004385 358.899624 -4.521 8.37e-06 ***
modPA_REC:groupdepressed 0.028707 0.006716 182.000000 4.274 3.09e-05 ***
modPA_REC:groupremitted 0.018436 0.005820 182.000000 3.167 0.0018 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) mdPA_REC grpdpr grprmt mdPA_REC:grpd
modPA_REC -0.664
groupdprssd -0.682 0.452
groupremttd -0.787 0.522 0.536
mdPA_REC:grpd 0.452 -0.682 -0.664 -0.356
mdPA_REC:grpr 0.522 -0.787 -0.356 -0.664 0.536
summary(lmer(condsd ~ mod*group + (1|sub), data = df_ref_rem))
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: condsd ~ mod * group + (1 | sub)
Data: df_ref_rem
REML criterion at convergence: -3051.1
Scaled residuals:
Min 1Q Median 3Q Max
-4.6567 -0.3176 0.0405 0.5475 1.7631
Random effects:
Groups Name Variance Std.Dev.
sub (Intercept) 2.602e-06 0.001613
Residual 9.639e-06 0.003105
Number of obs: 368, groups: sub, 184
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 4.995e-02 4.806e-04 3.464e+02 103.932 < 2e-16 ***
modPA_REM -1.171e-02 6.031e-04 1.810e+02 -19.419 < 2e-16 ***
groupdepressed 6.612e-05 7.050e-04 3.464e+02 0.094 0.9253
groupremitted -1.070e-04 6.123e-04 3.464e+02 -0.175 0.8614
modPA_REM:groupdepressed -3.565e-03 8.848e-04 1.810e+02 -4.029 8.23e-05 ***
modPA_REM:groupremitted -1.531e-03 7.684e-04 1.810e+02 -1.992 0.0479 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) mdPA_REM grpdpr grprmt mdPA_REM:grpd
modPA_REM -0.627
groupdprssd -0.682 0.428
groupremttd -0.785 0.492 0.535
mdPA_REM:grpd 0.428 -0.682 -0.627 -0.336
mdPA_REM:grpr 0.492 -0.785 -0.336 -0.627 0.535
Plots
First we set our theme and fix the data for the figures we want
# Theme
ggtheme = theme(text = element_text(size = 8),
panel.background = element_rect(fill = "transparent"),
panel.grid.major = element_line(color = "grey90"),
panel.grid.minor = element_line(color = "grey100"),
panel.border = element_rect(color = "grey80", fill = "transparent"))
# Estimate the SD
df_medal_clean2 = df_medal_clean %>%
mutate(pos_mood_sd = ifelse( (pos_mood_cs_lag_rec > (mean(pos_mood_cs_lag_rec, na.rm=T)+sd(pos_mood_cs_lag_rec, na.rm=T))), "+1SD",
ifelse( (pos_mood_cs_lag_rec < (mean(pos_mood_cs_lag_rec, na.rm=T)-sd(pos_mood_cs_lag_rec, na.rm =T))), "-1SD", "Mean"))) %>%
mutate(neg_mood_sd = ifelse( (neg_mood_cs_lag_rec > (mean(neg_mood_cs_lag_rec, na.rm=T)+sd(neg_mood_cs_lag_rec, na.rm=T))), "+1SD",
ifelse( (neg_mood_cs_lag_rec < (mean(neg_mood_cs_lag_rec, na.rm=T)-sd(neg_mood_cs_lag_rec, na.rm =T))), "-1SD", "Mean")))
# Fix factor levels
df_medal_clean2$Condition = factor(df_medal_clean2$condition, levels=c('control', 'remitted', 'depressed' ), labels=c('Never-Depressed', 'Remitted', 'Depressed'))
df_medal_clean2$pos_mood_sd = factor(df_medal_clean2$pos_mood_sd, levels=c('-1SD', 'Mean', '+1SD' ))
df_medal_clean2$neg_mood_sd = factor(df_medal_clean2$neg_mood_sd, levels=c('-1SD', 'Mean', '+1SD' ))
PA-CUR-REC
# Plot
plot_pa_rec = ggplot(df_medal_clean2, aes(x = rec_mem_pos_mood_c_lag, y=pos_mood_c, color = pos_mood_sd, fill = pos_mood_sd)) +
geom_smooth(method = 'lm', alpha = 0.15) +
labs( x = bquote(paste(REC[PM], " (subject-centered a.u.)")), y = "PM (subject-centered a.u.)", color = bquote(CUR[PM]), fill = bquote(CUR[PM]) ) +
ggtheme +
facet_grid(.~Condition)
plot_pa_rec
`geom_smooth()` using formula = 'y ~ x'
Warning: Removed 4237 rows containing non-finite values (`stat_smooth()`).

PA-CUR-REC
# Plot
plot_na_rec =
ggplot(df_medal_clean2, aes(x = rec_mem_neg_mood_c_lag, y=neg_mood_c, color = neg_mood_sd, fill = neg_mood_sd)) +
geom_smooth(method = 'lm', alpha = 0.15) +
labs( x = bquote(paste(REC['NM'], " (subject-centered a.u.)")), y = "NM (subject-centered a.u.)", color = bquote(CUR["NM"]), fill = bquote(CUR["NM"]) )+
ggtheme +
facet_grid(.~Condition)
plot_na_rec
`geom_smooth()` using formula = 'y ~ x'
Warning: Removed 4239 rows containing non-finite values (`stat_smooth()`).

Combined Plot for pub
ggarrange(NA, plot_pa_rec, NA, plot_na_rec,
widths=c(0.05, 1, 0.05, 1), ncol = 2, nrow = 2,
labels=c("A", NA, "B"))
Warning in as_grob.default(plot) :
Cannot convert object of class logical into a grob.
`geom_smooth()` using formula = 'y ~ x'
Warning: Removed 4237 rows containing non-finite values (`stat_smooth()`).
Warning in as_grob.default(plot) :
Cannot convert object of class logical into a grob.
`geom_smooth()` using formula = 'y ~ x'
Warning: Removed 4239 rows containing non-finite values (`stat_smooth()`).
Warning: Removed 1 rows containing missing values (`geom_text()`).
ggsave("figures/figure_2_threewayInteraction.pdf", device = 'pdf', dpi = 320, height = 6)
Saving 7.29 x 6 in image
Warning: Removed 1 rows containing missing values (`geom_text()`).

LS0tDQp0aXRsZTogJ01hbmlmZXN0YXRpb25zIG9mIG1lbW9yeSBiaWFzIGluIGRhaWx5IGxpZmUgaW4gY3VycmVudGx5IGFuZCByZW1pdHRlZCBkZXByZXNzZWQgaW5kaXZpZHVhbHM6IEhvdyBhY2N1cmF0ZSBpcyByZWNhbGwgb2YgcGFzdCBtb29kIHN0YXRlcz8nDQphdXRob3I6IFJheXlhbiBUdXR1bmppLCBOb2EgTWFndXNpbiwgTmVzc2EgSWthbmksIEphbm5hIFZyaWpzZW4NCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICBmaWdfd2lkdGg6IDgNCiAgICBmaWdfaGVpZ2h0OiA4DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IGZsYXRseQ0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRoZW1lOiBmbGF0bHkNCi0tLQ0KDQojIEludHJvZHVjdGlvbg0KDQpUaGlzIG5vdGVib29rIGNvbnRhaW5zIGFuYWx5c2VzIGZyb20gdGhlIE1FREFMIHN0dWR5LCBhc3Nlc3NpbmcgbWVtb3J5IGJpYXMgaW4gcmVtaXR0ZWQgYW5kIGRlcHJlc3NlZCBpbmRpdmlkdWFscy4gVGhlIHByZS1yZWdpc3RyYXRpb24gZm9yIHRoZSBtYWluIGFuYWx5c2VzLCBhcyB3ZWxsIGFzIGEgcHJlcHJpbnQgdmVyc2lvbiBvZiB0aGUgYWNjb21wYW55aW5nIGFydGljbGUgY2FuIGJlIGZvdW5kIFtoZXJlXShodHRwczovL29zZi5pby96dWZqcy8pIGFzIHdlbGwuIFRoZSBtYWluIGFpbSBvZiB0aGUgY3VycmVudCB3b3JrIHdhcyB0byBleGFtaW5lIGhvdyB0aHJlZSBncm91cHMgKGNvbnRyb2wsIHJlbWl0dGVkLCBkZXByZXNzZWQpIGRpZmZlciBpbiB0ZXJtcyBvZiBlbW90aW9uYWwgbWVtb3J5IGR5bmFtaWNzIGluIGEgcmVhbC1saWZlIHNldHRpbmcuDQoNCmBgYHtyIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRX0NCiNMb2FkIHBhY2thZ2VzIA0KcmVudjo6YWN0aXZhdGUoKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwc3ljaCkNCmxpYnJhcnkoZGV2dG9vbHMpDQpsaWJyYXJ5KHBhc3RlY3MpDQpsaWJyYXJ5KGNsaSkNCmxpYnJhcnkobG1lclRlc3QpICNsaW5lYXIgbWl4ZWQgbW9kZWxzIA0KbGlicmFyeShwZXJmb3JtYW5jZSkgI2ZpdHMgb2YgcmVzaWR1YWxzIA0KbGlicmFyeShEZXNjVG9vbHMpDQpsaWJyYXJ5KHRpZHlyKSAjIFNlcGFyYXRlIHRyaWdnZXIgY29sdW1uDQpsaWJyYXJ5KHNqUGxvdCkgIyBmb3IgbmljZSB0YWJsZXMgYW5kIGludGVyYWN0aW9uIHBsb3RzIA0KbGlicmFyeShrbml0cikgIyB0byBwcmludCB0aGUgdGFibGVzIHdpdGhpbiBub3RlYm9vaw0KbGlicmFyeShmb3JlYWNoKSAjcnVuIHBhcmFsbGVsIGxvb3BzDQpsaWJyYXJ5KHBhcmFsbGVsKQ0KbGlicmFyeShkb1BhcmFsbGVsKSAjcnVuIHBhcmFsbGVsIGxvb3BzDQpsaWJyYXJ5KGdncHVicikgIyBlbW1lYW5zDQpsaWJyYXJ5KG1lZGlhdGlvbikgI21lZGlhdGlvbiBhbmFseXNpcyANCmxpYnJhcnkocGxvdGx5KSAjZm9yIGludGVyYWN0aXZlIHBsb3RzDQpsaWJyYXJ5KGp0b29scykgI2ZvciB0aGVtZV9hcGENCmxpYnJhcnkoSlNtZWRpYXRpb24pICNtb2RlcmF0ZWQgbWVkaWF0aW9uDQpsaWJyYXJ5KHdlc2FuZGVyc29uKSANCnNvdXJjZSgiZnVuY3Rpb25zLlIiKQ0KYGBgDQoNCiMgRGF0YQ0KDQpIZXJlIHdlIGxvYWQgaW4gb3VyIGRhdGEgYW5kIHByZXByb2Nlc3MgaXQgaW4gc3RlcHMuIFdlIGZpcnN0IG5lZWQgdG8gc2VwYXJhdGUgdGhlIGRpZmZlcmVudCBzdXJ2ZXlzIHRoYXQgd2VyZSBkZWxpdmVyZWQgdG8gYnJpbmcgdGhlbSBpbnRvIHRoZSBzYW1lIHNhbXBsaW5nIHRpbWVzLCBtZXJnZSBpbiBzb21lIGRlc2NyaXB0aXZlcyB3ZSBuZWVkIGFzIGNvdmFyaWF0ZXMsIGFuZCBlc3RpbWF0ZSBzdWJqZWN0LWNlbnRlcmVkIGFuZCBsYWdnZWQgdmFyaWFibGVzIGZvciBvdXIgbW9kZWxzIGxhdGVyLiANCg0KDQoxLiBMb2FkIGFuZCBjbGVhbiBkYXRhDQoNCmBgYHtyfQ0KIyBMb2FkIHRoZSBkYXRhDQpNRURBTF9FU01fY29tcGxlZXQgPC0gcmVhZF9leGNlbCgiZGF0YS9NRURBTF9FU01fY29tcGxlZXQueGxzeCIpDQojIE1vdmUgdmFyaWFibGVzIGFyb3VuZCBhbmQgY2xlYW4gbmFtZXMNCk1FREFMX0VTTV9jb21wbGVldD0gTUVEQUxfRVNNX2NvbXBsZWV0ICU+JQ0KICByZW5hbWUoaWQ9J01vdmlzZW5zLUlEJykgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JQ0KICByZW5hbWUoc3ViamVjdGNvZGUgPSAnZGVlbG5lbWVyc25yJykgJT4lIA0KICByZWxvY2F0ZSgnc3ViamVjdGNvZGUnLCAuYWZ0ZXIgPSAnaWQnKQ0KZGZfbWVkYWxfdHJ5ID0gTUVEQUxfRVNNX2NvbXBsZWV0DQoNCmBgYA0KDQoyLiBTcGxpdCBkaWZmZXJlbnQgRU1BIHN1cnZleXMgd2UgaGF2ZQ0KDQpgYGB7cn0NCiMgU2xlZXAgRU1BIFFzDQpkZl9tZWRhbF9zbGVlcCA9IGRmX21lZGFsX3RyeSAlPiUgDQogIGZpbHRlcihmb3JtPT0nU2xhYXAnKSAlPiUgDQogIGRwbHlyOjpzZWxlY3QoYygxLCAyLCA0LCA1LCA3LCA5LCAxNCkpIA0KIyBSZWNlbnQgRU1BIFFzDQpkZl9tZWRhbF9yZWNlbnQgPSBkZl9tZWRhbF90cnkgJT4lIA0KICBmaWx0ZXIoZm9ybT09J1JlY2VudCcpICU+JSANCiAgZHBseXI6OnNlbGVjdChjKDEsIDIsIDQsIDUsIDcsIDksIGNvbnRhaW5zKCdyZWMnKSkpDQojIFJlbW90ZSBFTUEgUXMNCmRmX21lZGFsX3JlbW90ZSA9IGRmX21lZGFsX3RyeSAlPiUNCiAgZmlsdGVyKGZvcm09PSdSZW1vdGUnKSAlPiUNCiAgZHBseXI6OnNlbGVjdChjKDEsIDIsIDQsIDUsIDcsIDksIGNvbnRhaW5zKCdyZW0nKSkpDQojIE1hc3RlcnkgRU1BIFFzDQpkZl9tZWRhbF9tYXN0ZXJ5ID0gZGZfbWVkYWxfdHJ5ICU+JQ0KICBmaWx0ZXIoZm9ybT09J01hc3RlcnknKSAlPiUgDQogIGRwbHlyOjpzZWxlY3QoYygxLCAyLCA0LCA1LCA3LCA5LCBjb250YWlucygnbWFzdGVyJykpKQ0KIyBTdGFuZGFyZCBRcw0KZGZfbWVkYWxfc3RhbmRhcmQgPSBkZl9tZWRhbF90cnkgJT4lDQogIGZpbHRlcihmb3JtPT0nU3RhbmRhYXJkJykgICU+JQ0KICBkcGx5cjo6c2VsZWN0KGMoMSwgMiwgNCwgNSwgNywgOSwgKC1jb250YWlucygnbWFzdGVyeScpICYgLWNvbnRhaW5zKCdyZW0nKSAmIC1jb250YWlucygncmVjJykpKSkgJT4lIA0KICBkcGx5cjo6c2VsZWN0KC1jKDcsMTMsMTQpKQ0KDQojIG1lcmdlIHNsZWVwIGFuZCBzdGFuZGFyZA0KZGZfbWVkYWxfbWVyZ2VkID0gbWVyZ2UoZGZfbWVkYWxfc2xlZXAsIGRmX21lZGFsX3N0YW5kYXJkLCBieT1jKCdpZCcsICd0cmlnZ2VyX2NvdW50ZXInLCAnc3ViamVjdGNvZGUnKSwgc3VmZml4ZXMgPSBjKCJfc2xlZXAiLCAiIiksIGFsbD1UICkNCg0KIyBtZXJnZSB0byByZWNlbnQsIHJlbW90ZSBhbmQgbWFzdGVyeQ0KZGZfbWVkYWxfbWVyZ2VkPSBtZXJnZShkZl9tZWRhbF9tZXJnZWQsIGRmX21lZGFsX3JlY2VudCwgYnk9YygnaWQnLCAndHJpZ2dlcl9jb3VudGVyJywgJ3N1YmplY3Rjb2RlJyApLCBzdWZmaXhlcyA9IGMoJycsICdfcmVjZW50JyksIGFsbCA9IFQgKQ0KZGZfbWVkYWxfbWVyZ2VkID0gbWVyZ2UoZGZfbWVkYWxfbWVyZ2VkLCBkZl9tZWRhbF9yZW1vdGUsIGJ5PWMoJ2lkJywgJ3RyaWdnZXJfY291bnRlcicsICdzdWJqZWN0Y29kZScgKSwgc3VmZml4ZXMgPSBjKCcnLCAnX3JlbW90ZScpLCBhbGwgPSBUICkNCmRmX21lZGFsX21lcmdlZCA9IG1lcmdlKGRmX21lZGFsX21lcmdlZCwgZGZfbWVkYWxfbWFzdGVyeSwgYnk9YygnaWQnLCAndHJpZ2dlcl9jb3VudGVyJywgJ3N1YmplY3Rjb2RlJyApLCBzdWZmaXhlcyA9IGMoJycsICdfbWFzdGVyeScpLCBhbGwgPSBUICkNCg0KIyBGaXggc3RhcnQgZGF0ZXMgYW5kIHRpbWVzDQpkZl9tZWRhbF9tZXJnZWQkZm9ybV9zdGFydF9kYXRlIDwtIGFzLmNoYXJhY3RlcihkZl9tZWRhbF9tZXJnZWQkZm9ybV9zdGFydF9kYXRlKQ0KZGZfbWVkYWxfbWVyZ2VkJGZvcm1fc3RhcnRfZGF0ZSA8LSBhcy5JVGltZShkZl9tZWRhbF9tZXJnZWQkZm9ybV9zdGFydF9kYXRlKQ0KZGZfbWVkYWxfbWVyZ2VkID0gZGZfbWVkYWxfbWVyZ2VkICU+JSANCiAgZHBseXI6Om11dGF0ZShmb3JtX3N0YXJ0X2RhdGUgPSBpZmVsc2UoaXMubmEoZm9ybV9zdGFydF9kYXRlKSwgZm9ybV9zdGFydF9kYXRlX3NsZWVwLCBmb3JtX3N0YXJ0X2RhdGUpKQ0KYGBgDQoNCjMuIEFkZCB2YXJpYWJsZXMgb24gRWR1Y2F0aW9uLCBHZW5kZXIsIGFuZCBBZ2UNCg0KYGBge3J9DQojIExvYWQgaW4gcHJldmlvdXMgZGF0YSBmb3IgZGVtb2dyYXBoaWNzIChhbHNvIGNvbnRhaW5zIEVNQSkNCmxvYWQoImRhdGEvSVBBUV9NYWV2ZV9Xb3Jrc3BhY2UuUkRhdGEiKQ0KZGZfTUVEQUwgPC0gZGZfTUVEQUxbLWMoMTkyKSwgXQ0KDQojIFNlbGVjdCByZWxldmFudCBkZW1vIGluZm8NCmRmX01FREFMID0gZGZfTUVEQUwgJT4lIA0KICBkcGx5cjo6c2VsZWN0KDEsIDMsIDU6NykgJT4lIA0KICByZW5hbWUoJ3N1YmplY3Rjb2RlJyA9ICdzdWJqZWN0JywgJ2VkdWNhdGlvbicgPSAnRWR1Y2F0aW9uM2dyb3VwcycsICduX2VwaXNvZGVzJz0nTnVtYmVyRXBpc29kZXMnICkNCg0KIyBtZXJnZSBkZW1vIHRvIGZ1bGwgRU1BDQpkZl9tZWRhbF9tZXJnZWQgPSAgbWVyZ2UoZGZfbWVkYWxfbWVyZ2VkLCBkZl9NRURBTCwgYnkgPSBjKCdzdWJqZWN0Y29kZScpLCBhbGwgPSBUICkgJT4lDQogIGNsZWFuX25hbWVzKCkgDQoNCmRmX21lZGFsX21lcmdlZCRlZHVjYXRpb24gPSBhcy5mYWN0b3IoZGZfbWVkYWxfbWVyZ2VkJGVkdWNhdGlvbikNCmRmX21lZGFsX21lcmdlZCRnZW5kZXIgPSBhcy5mYWN0b3IoZGZfbWVkYWxfbWVyZ2VkJGdlbmRlcikNCg0KZGZfbWVkYWxfbWVyZ2VkID0gZGZfbWVkYWxfbWVyZ2VkICU+JSANCiAgcmVsb2NhdGUoYygnaWQnLCAnZ2VuZGVyJywgJ2FnZScsICdlZHVjYXRpb24nKSwgLmFmdGVyID0gJ3N1YmplY3Rjb2RlJykgJT4lIA0KICByZWxvY2F0ZSAoJ2FnZScsIC5hZnRlciA9ICdnZW5kZXInKSAlPiUgDQogIHJlbG9jYXRlICgnZWR1Y2F0aW9uJywgLmFmdGVyID0gJ2FnZScpICU+JSANCiAgcmVsb2NhdGUgKCdpZCcsIC5iZWZvcmUgPSAnc3ViamVjdGNvZGUnKQ0KDQpgYGANCg0KNC4gQ2F0ZWdvcml6ZSB0aGUgc3ViamVjdGNvZGUgaW50byB0aGUgdGhyZWUgY29uZGl0aW9ucyAoRGVwcmVzc2VkLCBSZW1pdHRlZCwgQ29udHJvbCAoTmV2ZXItZGVwcmVzc2VkKSkNCg0KYGBge3J9DQpkZl9tZWRhbF9tZXJnZWQkY29uZGl0aW9uID0gY2FzZV93aGVuKGRmX21lZGFsX21lcmdlZCRzdWJqZWN0Y29kZSA+PSA3MDAgJiBkZl9tZWRhbF9tZXJnZWQkc3ViamVjdGNvZGUgPCA4MDAgfiAicmVtaXR0ZWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZl9tZWRhbF9tZXJnZWQkc3ViamVjdGNvZGUgPj0gODAwICYgZGZfbWVkYWxfbWVyZ2VkJHN1YmplY3Rjb2RlIDwgOTAwIH4gImRlcHJlc3NlZCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZl9tZWRhbF9tZXJnZWQkc3ViamVjdGNvZGUgPj0gOTAwIH4gImNvbnRyb2wiKQ0KZGZfbWVkYWxfbWVyZ2VkID0gZGZfbWVkYWxfbWVyZ2VkICU+JSByZWxvY2F0ZSAoJ2NvbmRpdGlvbicsIC5hZnRlciA9ICdzdWJqZWN0Y29kZScgKQ0KZGZfbWVkYWxfbWVyZ2VkJGNvbmRpdGlvbiA8LSBhcy5mYWN0b3IoZGZfbWVkYWxfbWVyZ2VkJGNvbmRpdGlvbikNCmBgYA0KDQo1LiBDYWxjdWxhdGUgcmVhY3Rpb24gdGltZSANCg0KYGBge3J9DQpkZl9tZWRhbF9tZXJnZWQkcnRfc2xlZXAgPSBsdWJyaWRhdGU6OmFzLmRpZmZ0aW1lKCBkZl9tZWRhbF9tZXJnZWQkZm9ybV9maW5pc2hfZGF0ZV9zbGVlcCAtIGRmX21lZGFsX21lcmdlZCRmb3JtX3N0YXJ0X2RhdGVfc2xlZXApDQpgYGANCg0KNi4gU2VwYXJhdGUgdGltZSBmcm9tIHdoZW4gdHJpZ2dlciB3YXMgc2VudA0KDQpgYGB7cn0NCg0KZGZfbWVkYWxfbWVyZ2VkID0gZGZfbWVkYWxfbWVyZ2VkICU+JSANCiAgdGlkeXI6OnNlcGFyYXRlKHRyaWdnZXIsIGMoJ1JhbmRvbScsICdUaW1lJywgJ1RyaWdnZXJfVGltZV8xJywgJ1RyaWdnZXJfVGltZV8yJykpICAlPiUgDQogIGRwbHlyOjptdXRhdGUodHJpZ2dlcl90aW1lID0gcGFzdGUoVHJpZ2dlcl9UaW1lXzEsIFRyaWdnZXJfVGltZV8yLCBzZXA9JzonKSkgJT4lI3NlcGFyYXRlIHRpbWUgZnJvbSBwcmV2aW91cyB0cmlnZ2VyDQogIGRwbHlyOjptdXRhdGUodHJpZ2dlciA9IHBhc3RlKFJhbmRvbSwgVGltZSwgdHJpZ2dlcl90aW1lLCBzZXA9JyAnKSkgI2JyaW5nIGJhY2sgJ3RyaWdnZXInIGNvbHVtbiANCg0KI1R1cm4gbnVtYmVycyBpbnRvIHRpbWUgZm9ybWF0DQpkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl90aW1lIDwtIGFzLklUaW1lKGRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUpDQpgYGANCg0KNy4gRmluZCB0aGUgdHJpZ2dlciBudW1iZXIgcGVyIGRheQ0KDQpgYGB7cn0NCiNkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl9jb3VudGVyW2lzLm5hKGRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUpXSA8LSAxDQoNCmRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX251bWJlcltpcy5uYShkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl90aW1lKV0gPC0gMSANCmRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX251bWJlcltkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl90aW1lID49IChhcy5JVGltZSgiMTA6MDA6MDAiKSkmIGRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUgPCAoYXMuSVRpbWUoIjEyOjAwOjAwIikpXSA8LSAyDQpkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl9udW1iZXJbZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfdGltZSA+PSAoYXMuSVRpbWUoIjEyOjAwOjAwIikpJiBkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl90aW1lIDwgKGFzLklUaW1lKCIxNDowMDowMCIpKV0gPC0gMw0KZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfbnVtYmVyW2RmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUgPj0gKGFzLklUaW1lKCIxNDowMDowMCIpKSYgZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfdGltZSA8IChhcy5JVGltZSgiMTY6MDA6MDAiKSldIDwtIDQNCmRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX251bWJlcltkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl90aW1lID49IChhcy5JVGltZSgiMTY6MDA6MDAiKSkmIGRmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUgPCAoYXMuSVRpbWUoIjE4OjAwOjAwIikpXSA8LSA1DQpkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl9udW1iZXJbZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfdGltZSA+PSAoYXMuSVRpbWUoIjE4OjAwOjAwIikpJiBkZl9tZWRhbF9tZXJnZWQkdHJpZ2dlcl90aW1lIDwgKGFzLklUaW1lKCIyMDowMDowMCIpKV0gPC0gNg0KZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfbnVtYmVyW2RmX21lZGFsX21lcmdlZCR0cmlnZ2VyX3RpbWUgPj0gKGFzLklUaW1lKCIyMDowMDowMCIpKSYgZGZfbWVkYWxfbWVyZ2VkJHRyaWdnZXJfdGltZSA8IChhcy5JVGltZSgiMjM6MDA6MDEiKSldIDwtIDcNCg0KIyBkZg0KZGZfbWVkYWxfbWVyZ2VkID0gZGZfbWVkYWxfbWVyZ2VkICU+JSANCiAgcmVsb2NhdGUgKCd0cmlnZ2VyX251bWJlcicsIC5hZnRlciA9ICd0cmlnZ2VyX2NvdW50ZXInKSU+JSByZWxvY2F0ZSgndHJpZ2dlcl90aW1lJywgLmJlZm9yZSA9J2Zvcm1fc3RhcnRfZGF0ZScpICU+JQ0KICByZWxvY2F0ZSgndHJpZ2dlcicsIC5iZWZvcmUgPSd0cmlnZ2VyX3RpbWUnKQ0KYGBgDQoNCjguIEZpbmFsIGNsZWFuaW5nIG9mIHRoZSBkYXRhc2V0DQpgYGB7cn0NCg0KI0NyZWF0ZSBkYXRhc2V0IHdoZXJlIGRvdWJsZSBtb3JuaW5nIGxpc3QgaXMgcmVtb3ZlZCANCmRmX21lZGFsX21lcmdlZCA9IGRmX21lZGFsX21lcmdlZCAlPiUgDQogIGRwbHlyOjptdXRhdGUodHJpZ2dlcl9jb3VudGVyPWlmZWxzZSh0cmlnZ2VyX251bWJlcj09MSAmIGxhZyh0cmlnZ2VyX251bWJlcik9PTEsIGxhZyh0cmlnZ2VyX2NvdW50ZXIpLCB0cmlnZ2VyX2NvdW50ZXIpKSAlPiUgDQogIGRwbHlyOjptdXRhdGUodHJpZ2dlcl9jb3VudGVyPWlmZWxzZSh0cmlnZ2VyX251bWJlcj09MSAmIGxhZyh0cmlnZ2VyX251bWJlcik9PTEsIGxhZyh0cmlnZ2VyX2NvdW50ZXIpLCB0cmlnZ2VyX2NvdW50ZXIpKSAlPiUNCiAgZHBseXI6Om11dGF0ZSh0cmlnZ2VyX2NvdW50ZXI9aWZlbHNlKHRyaWdnZXJfbnVtYmVyPT0xICYgbGFnKHRyaWdnZXJfbnVtYmVyKT09MSwgbGFnKHRyaWdnZXJfY291bnRlciksIHRyaWdnZXJfY291bnRlcikpICU+JQ0KICBkcGx5cjo6bXV0YXRlKHRyaWdnZXJfY291bnRlcj1pZmVsc2UodHJpZ2dlcl9udW1iZXI9PTEgJiBsYWcodHJpZ2dlcl9udW1iZXIpPT0xLCBsYWcodHJpZ2dlcl9jb3VudGVyKSwgdHJpZ2dlcl9jb3VudGVyKSkgJT4lIA0KICBkcGx5cjo6bXV0YXRlKHRyaWdnZXJfY291bnRlcj1pZmVsc2UodHJpZ2dlcl9udW1iZXI9PTEgJiBsYWcodHJpZ2dlcl9udW1iZXIpPT0xLCBsYWcodHJpZ2dlcl9jb3VudGVyKSwgdHJpZ2dlcl9jb3VudGVyKSkNCg0KIyBub3cgd2UgaGF2ZSB0aGUgY2xlYW4gZGF0YWZyYW1lLCByZW1vdmUgZHVwbGljYXRlZCBjb2xvdW1ucw0KZGZfbWVkYWxfY2xlYW4gPSBkZl9tZWRhbF9tZXJnZWQgJT4lDQogIGRwbHlyOjpncm91cF9ieShzdWJqZWN0Y29kZSkgJT4lIA0KICBkaXN0aW5jdCh0cmlnZ2VyX2NvdW50ZXIsIC5rZWVwX2FsbCA9IFRSVUUpICU+JSANCiAgZHBseXI6OnNlbGVjdCAoMToxMiwgMTc6NjApICU+JSANCiAgZHBseXI6Om11dGF0ZShvcmlnaW5hbF9vcmRlciA9IHJvd19udW1iZXIoKSkgJT4lIA0KICByZWxvY2F0ZSgnb3JpZ2luYWxfb3JkZXInLCAuYmVmb3JlID0gJ2lkJykNCg0KI1NldCB0aGUgb3JkZXIgb2YgdGhlIGZhY3RvciB0byBjb250cm9sLCByZW1pc3Npb24sIGRlcHJlc3Npb24gKGZvciB2aXN1YWwgcHVycG9zZXMpDQpkZl9tZWRhbF9jbGVhbiRjb25kaXRpb24gPC0gZmFjdG9yKGRmX21lZGFsX2NsZWFuJGNvbmRpdGlvbiwgbGV2ZWxzPWMoJ2NvbnRyb2wnLCAncmVtaXR0ZWQnLCAnZGVwcmVzc2VkJyApLCBsYWJlbHM9YygnY29udHJvbCcsICdyZW1pdHRlZCcsICdkZXByZXNzZWQnKSkNCg0KIyBDcmVhdGUgZHVtbXkgdmFyaWFibGUgDQpkZl9tZWRhbF9jbGVhbiA9IGRmX21lZGFsX2NsZWFuICU+JSANCiAgbXV0YXRlKGNvbmRpdGlvbl9kdW1teSA9IGNhc2Vfd2hlbihjb25kaXRpb24gPT0gJ2RlcHJlc3NlZCd+IDMsIGNvbmRpdGlvbiA9PSAncmVtaXR0ZWQnfiAyLCBjb25kaXRpb24gPT0gJ2NvbnRyb2wnIH4gMSkpDQoNCmRmX21lZGFsX2NsZWFuJGNvbmRpdGlvbl9kdW1teSA9IGFzLmZhY3RvcihkZl9tZWRhbF9jbGVhbiRjb25kaXRpb25fZHVtbXkpDQoNCiNzZXQgd2Vla2RheSANCmRmX21lZGFsX2NsZWFuJGZvcm1fZmluaXNoX2RhdGUgPC0gYXMuY2hhcmFjdGVyKGRmX21lZGFsX2NsZWFuJGZvcm1fZmluaXNoX2RhdGUpDQpkZl9tZWRhbF9jbGVhbiRmb3JtX2ZpbmlzaF9kYXRlIDwtIHN0cnB0aW1lKGRmX21lZGFsX2NsZWFuJGZvcm1fZmluaXNoX2RhdGUsIGZvcm1hdCA9ICclWS0lbS0lZCAlSDolTTolUycpDQoNCmRmX21lZGFsX2NsZWFuJGZpbmlzaF9kYXRlIDwtIGFzLkRhdGUoZGZfbWVkYWxfY2xlYW4kZm9ybV9maW5pc2hfZGF0ZSkNCmRmX21lZGFsX2NsZWFuJHdlZWtkYXkgPC0gYXMuaW50ZWdlcihmb3JtYXQoZGZfbWVkYWxfY2xlYW4kZmluaXNoX2RhdGUsICcldycpKQ0KZGZfbWVkYWxfY2xlYW4gPSBkZl9tZWRhbF9jbGVhbiAlPiUgcmVsb2NhdGUoJ3dlZWtkYXknLCAuYWZ0ZXIgPSAndHJpZ2dlcl9udW1iZXInKQ0KDQojc29sdmUgZHVwbGljYXRlIGlzc3VlIA0KZGZfbWVkYWxfZHVwbGljYXRlID0gZGZfbWVkYWxfY2xlYW4gJT4lIGRwbHlyOjpncm91cF9ieShzdWJqZWN0Y29kZSwgd2Vla2RheSkgJT4lIGZpbHRlcihkdXBsaWNhdGVkKHRyaWdnZXJfbnVtYmVyKSkNCg0KICAjc2luY2Ugcm93IDEwIGZvciBzdWJqZWN0IDcxMiBpcyBhIGR1cGxpY2F0ZSBtb3JuaW5nIGxpc3QNCiAgZGZfbWVkYWxfY2xlYW4gPC0gc3Vic2V0KGRmX21lZGFsX2NsZWFuLCAhKHN1YmplY3Rjb2RlID09IDcxMiAmIG9yaWdpbmFsX29yZGVyID09IDEwKSkNCiAgZGZfbWVkYWxfY2xlYW4gPSBkZl9tZWRhbF9jbGVhbiAlPiUgZHBseXI6Omdyb3VwX2J5KHN1YmplY3Rjb2RlLCB3ZWVrZGF5KSAlPiUgDQogICAgbXV0YXRlKHRlbXAgPSBsZWFkKHRyaWdnZXJfbnVtYmVyKSwgDQogICAgICAgICAgIHRyaWdnZXJfbnVtYmVyID0gY2FzZV93aGVuKHRyaWdnZXJfbnVtYmVyID09IHRlbXAgfiAodGVtcCAtMSksIFRSVUUgfiB0cmlnZ2VyX251bWJlcikpICU+JQ0KICAgIHNlbGVjdCgtdGVtcCkNCiAgI1Rha2UgdGhlIHJvd3Mgb3V0IHRoYXQgaGF2ZSAnTkEnZm9yIHRoZSB3ZWVrZGF5IHNpbmNlIGZvcm0gd2Fzbid0IGZpbmlzaGVkIGFuZCB0aGVyZSBpcyBubyBkYXRhIGZvciBQQSwgTkEsIG9yIE1lbW9yeQ0KICBkZl9tZWRhbF9jbGVhbiA9IGRmX21lZGFsX2NsZWFuICU+JSBmaWx0ZXIoIWlzLm5hKHdlZWtkYXkpKQ0KICBkZl9tZWRhbF9jbGVhbiRvcmlnaW5hbF9vcmRlciA8LSAxOm5yb3coZGZfbWVkYWxfY2xlYW4pIA0KDQojIENyZWF0ZSBleHBhbmRlZCBkZiB3aXRoIGFsbCBwb3RlbnRpYWwgZGF0YXBvaW50cw0KDQpkZl9tZWRhbF9kYXkgPSBkZl9tZWRhbF9jbGVhbiAlPiUgDQogIGRwbHlyOjpzZWxlY3QoJ3N1YmplY3Rjb2RlJywgJ3dlZWtkYXknLCAnb3JpZ2luYWxfb3JkZXInKSAlPiUgDQogIGRwbHlyOjptdXRhdGUod2Vla2RheSA9IGFzLm51bWVyaWMod2Vla2RheSkpICU+JQ0KICBkcGx5cjo6Z3JvdXBfYnkoc3ViamVjdGNvZGUpICU+JQ0KICBkcGx5cjo6IGRpc3RpbmN0KHdlZWtkYXksIC5rZWVwX2FsbCA9VCkgJT4lIA0KICBkcGx5cjo6dW5ncm91cCgpDQoNCmRmX21lZGFsX2RheSA9IGRmX21lZGFsX2RheSAlPiUgDQogIHNsaWNlKHJlcCgxOm4oKSwgZWFjaCA9IDcpKSAlPiUgDQogIGRwbHlyOjptdXRhdGUodHJpZ2dlcl9udW1iZXIgPSByZXAoMTo3LCBsZW5ndGgub3V0PW4oKSkpICU+JSANCiAgZHBseXI6OnJlbmFtZShvcmRlciA9IG9yaWdpbmFsX29yZGVyKQ0KDQoNCiNtZXJnZSB3aXRoIG1haW4gZGF0YWZyYW1lDQpkZl9tZWRhbF9jbGVhbiA9ICBtZXJnZShkZl9tZWRhbF9kYXksIGRmX21lZGFsX2NsZWFuLCBieT1jKCdzdWJqZWN0Y29kZScsICd0cmlnZ2VyX251bWJlcicsICd3ZWVrZGF5JyksIGFsbD0gVCkgDQpkZl9tZWRhbF9jbGVhbiA9IGRmX21lZGFsX2NsZWFuICU+JSBtdXRhdGUob3JkZXIgPSBhcy5udW1lcmljKG9yZGVyKSkNCmRmX21lZGFsX2NsZWFuID0gYXJyYW5nZShkZl9tZWRhbF9jbGVhbiwgb3JkZXIpDQpgYGANCg0KOS4gQ2VudHJlLCBzY2FsZSwgYW5kIGF2ZXJhZ2UgVmFyaWFibGVzIA0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFfQ0KDQp1c2VkX3ZhcnMgPSBjKCJuZWdfbW9vZCIsICJyZWNfbWVtX25lZ19tb29kIiwgInJlbV9tZW1fbmVnX21vb2QiLCAicG9zX21vb2QiLCAicmVjX21lbV9wb3NfbW9vZCIsICJyZW1fbWVtX3Bvc19tb29kIikNCg0KI0NlbnRlcmluZyAmIHNjYWxpbmcgDQpkZl9tZWRhbF9jbGVhbiA9IGRmX21lZGFsX2NsZWFuICU+JSANCiAgZHBseXI6Omdyb3VwX2J5KHN1YmplY3Rjb2RlKSAlPiUNCiAgIyBDZW50ZXIgYW5kIHNjYWxlDQogIGRwbHlyOjptdXRhdGUoIGFjcm9zcyh1c2VkX3ZhcnMsIH4gKC54LzEwKSwgLm5hbWVzID0gInsuY29sfSIgKSwNCiAgICAgICAgICAgICAgICAgYWNyb3NzKHVzZWRfdmFycywgfiBtZWFuKC54LCBuYS5ybT1UKSwgLm5hbWVzID0gInsuY29sfV9tIiApLA0KICAgICAgICAgICAgICAgICBhY3Jvc3ModXNlZF92YXJzLCB+ICgueCAtIG1lYW4oLngsIG5hLnJtPVQpKSwgLm5hbWVzID0gInsuY29sfV9jIiApLCANCiAgICAgICAgICAgICAgICAgYWNyb3NzKHBhc3RlMCh1c2VkX3ZhcnMsICJfYyIpLCB+IERlc2NUb29sczo6V2luc29yaXplKC54LCBuYS5ybSA9IFQpLCAubmFtZXMgPSAiey5jb2x9IikpICU+JSAgDQogIHVuZ3JvdXAoKSAlPiUNCiAgIyBSZXNjYWxlIHRvIHBvc2l0aXZlDQogIG11dGF0ZShhY3Jvc3MoYyhwYXN0ZTAodXNlZF92YXJzLCJfYyIpKSwgfiBhYnMobWluKC54LCBuYS5ybSA9IFQpKSArIDEgKyAueCwgLm5hbWVzID0gInsuY29sfXMiKSkNCg0KYGBgDQoNCg0KMTAuIExhZyB2YXJpYWJsZXMgDQpgYGB7cn0NCiMgUmVtb3RlIA0KDQpkZl9tZWRhbF9jbGVhbiA9IGRmX21lZGFsX2NsZWFuICU+JQ0KICBkcGx5cjo6Z3JvdXBfYnkoc3ViamVjdGNvZGUpICU+JQ0KICBtdXRhdGUocmVtX21lbV9wb3NfbW9vZF9sYWcgPSBsZWFkKHJlbV9tZW1fcG9zX21vb2QsIG49Nywgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcmVtX21lbV9uZWdfbW9vZF9sYWcgPSBsZWFkKHJlbV9tZW1fbmVnX21vb2QsIG49Nywgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcG9zX21vb2RfbGFnX3JlbSA9IGxlYWQocG9zX21vb2QsIG49Nywgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgbmVnX21vb2RfbGFnX3JlbSA9IGxlYWQobmVnX21vb2QsIG49Nywgb3JkZXJfYnk9c3ViamVjdGNvZGUpLCANCiAgICAgICAgIHJlbV9tZW1fcG9zX21vb2RfY3NfbGFnID0gbGVhZChyZW1fbWVtX3Bvc19tb29kX2NzLCBuPTcsIG9yZGVyX2J5PXN1YmplY3Rjb2RlKSwNCiAgICAgICAgIHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnID0gbGVhZChyZW1fbWVtX25lZ19tb29kX2NzLCBuPTcsIG9yZGVyX2J5PXN1YmplY3Rjb2RlKSwNCiAgICAgICAgIHBvc19tb29kX2NzX2xhZ19yZW0gPSBsZWFkKHBvc19tb29kX2NzLCBuPTcsIG9yZGVyX2J5PXN1YmplY3Rjb2RlKSwNCiAgICAgICAgIG5lZ19tb29kX2NzX2xhZ19yZW0gPSBsZWFkKG5lZ19tb29kX2NzLCBuPTcsIG9yZGVyX2J5PXN1YmplY3Rjb2RlKSwNCiAgICAgICAgIHJlbV9tZW1fcG9zX21vb2RfY19sYWcgPSBsZWFkKHJlbV9tZW1fcG9zX21vb2RfYywgbj03LCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICByZW1fbWVtX25lZ19tb29kX2NfbGFnID0gbGVhZChyZW1fbWVtX25lZ19tb29kX2MsIG49Nywgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcG9zX21vb2RfY19sYWdfcmVtID0gbGVhZChwb3NfbW9vZF9jLCBuPTcsIG9yZGVyX2J5PXN1YmplY3Rjb2RlKSwNCiAgICAgICAgIG5lZ19tb29kX2NfbGFnX3JlbSA9IGxlYWQobmVnX21vb2RfYywgbj03LCBvcmRlcl9ieT1zdWJqZWN0Y29kZSkpICU+JSANCiAgZmlsdGVyKCFpcy5uYShvcmlnaW5hbF9vcmRlcikpICMgZmlsdGVyIG91dCB0aGUgTkEgcm93cyBmb3IgdGhlIGxhZ2dpbmcgb2YgcmVjZW50IG1lbW9yeSANCg0KIyBSZWNlbnQNCmRmX21lZGFsX2NsZWFuID0gZGZfbWVkYWxfY2xlYW4gJT4lIA0KICBkcGx5cjo6Z3JvdXBfYnkoc3ViamVjdGNvZGUpICU+JQ0KICBtdXRhdGUocmVjX21lbV9wb3NfbW9vZF9sYWcgPSBsZWFkKHJlY19tZW1fcG9zX21vb2QsIG49MSwgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcmVjX21lbV9uZWdfbW9vZF9sYWcgPSBsZWFkKHJlY19tZW1fbmVnX21vb2QsIG49MSwgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcG9zX21vb2RfbGFnX3JlYyA9IGxlYWQocG9zX21vb2QsIG49MSwgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgbmVnX21vb2RfbGFnX3JlYyA9IGxlYWQobmVnX21vb2QsIG49MSwgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcmVjX21lbV9wb3NfbW9vZF9jc19sYWcgPSBsZWFkKHJlY19tZW1fcG9zX21vb2RfY3MsIG49MSwgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcmVjX21lbV9uZWdfbW9vZF9jc19sYWcgPSBsZWFkKHJlY19tZW1fbmVnX21vb2RfY3MsIG49MSwgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcG9zX21vb2RfY3NfbGFnX3JlYyA9IGxlYWQocG9zX21vb2RfY3MsIG49MSwgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgbmVnX21vb2RfY3NfbGFnX3JlYyA9IGxlYWQobmVnX21vb2RfY3MsIG49MSwgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgcmVjX21lbV9wb3NfbW9vZF9jX2xhZyA9IGxlYWQocmVjX21lbV9wb3NfbW9vZF9jLCBuPTEsIG9yZGVyX2J5PXN1YmplY3Rjb2RlKSwNCiAgICAgICAgIHJlY19tZW1fbmVnX21vb2RfY19sYWcgPSBsZWFkKHJlY19tZW1fbmVnX21vb2RfYywgbj0xLCBvcmRlcl9ieT1zdWJqZWN0Y29kZSksDQogICAgICAgICBwb3NfbW9vZF9jX2xhZ19yZWMgPSBsZWFkKHBvc19tb29kX2MsIG49MSwgb3JkZXJfYnk9c3ViamVjdGNvZGUpLA0KICAgICAgICAgbmVnX21vb2RfY19sYWdfcmVjID0gbGVhZChuZWdfbW9vZF9jLCBuPTEsIG9yZGVyX2J5PXN1YmplY3Rjb2RlKSkgJT4lIA0KICB1bmdyb3VwKCkNCiAgDQoNCmBgYA0KDQojIERlc2NyaXB0aXZlcyB7LX0NCg0KV2UgZmlyc3QgcGxvdCBzb21lIGdlbmVyYWwgcG9wdWxhdGlvbiBkZXNjcmlwdGl2ZXMsIGZvbGxvd2VkIGJ5IHNvbWUgZGVzY3JpcHRpdmVzIG9mIHRoZSBzY2FsZXMgd2UgdXNlIGluIHRoZSBFTUEgd2Vla3MgYW5kIGNvbXBsaWFuY2UgcmF0ZXMgZm9yIGJvdGggcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIG1vb2QuDQoNCiMjIFBvcHVsYXRpb24gey0gLnRhYnNldH0NCg0KIyMjIERlbW9ncmFwaGljcyBUYWJsZSB7LX0NCmBgYHtyIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xMn0NCiNDcmVhdGUgRGVzY3JpcHRpdmVzIFRhYmxlcw0Kc3VtbWFyeV90YWJsZSA9IGRmX21lZGFsX2NsZWFuICU+JSBkaXN0aW5jdChzdWJqZWN0Y29kZSwgLmtlZXBfYWxsID0gVFJVRSkgJT4lIGdyb3VwX2J5KGNvbmRpdGlvbikgJT4lIHN1bW1hcmlzZSgNCiAgJ04nID0gbigpLA0KICAnQWdlIFxuIE0gKy8tIFNEJyA9IHBhc3RlMChyb3VuZChtZWFuKGFnZSwgbmEucm0gPVQpLCAxKSwgJyArLy0gJyAsIHJvdW5kKHNkKGFnZSwgbmEucm0gPVQpLCAxKSksDQogICMnTkEgQWdlJyA9IHN1bShpcy5uYShhZ2UpKSwgDQogICclIEVkdWNhdGlvbiBMb3cnID0gbWVhbihlZHVjYXRpb24gPT0gMCwgbmEucm0gPSBUKSoxMDAsDQogICclIEVkdWNhdGlvbiBNaWRkbGUnID0gbWVhbihlZHVjYXRpb24gPT0gMSwgbmEucm0gPSBUKSoxMDAsDQogICclIEVkdWNhdGlvbiBIaWdoJyA9IG1lYW4oZWR1Y2F0aW9uID09IDIsIG5hLnJtID0gVCkqMTAwLA0KICAjJ05BIEVkdWNhdGlvbicgPSBzdW0oaXMubmEoZWR1Y2F0aW9uKSksIA0KICAnJSBGZW1hbGUnID0gbWVhbihnZW5kZXIgPT0xLCBuYS5ybSA9IFQpKjEwMCwNCiAgIydOQSBHZW5kZXInID0gc3VtKGlzLm5hKGdlbmRlcikpDQopDQoNCiNDb21wbGlhbmNlIHJhdGVzDQpkZl9tZWRhbF9jb21wbGlhbmNlX2luZGl2aWR1YWwgPSBkZl9tZWRhbF9jbGVhbiAlPiUgZ3JvdXBfYnkoY29uZGl0aW9uLCBzdWJqZWN0Y29kZSkgJT4lIHN1bW1hcmlzZSgnQ29tcGxpYW5jZVJhdGUnID0gc3VtKCFpcy5uYSh0cmlnZ2VyX251bWJlcikpLzQyKjEwMCkNCg0KbGVuZ3RoKHdoaWNoKGRmX21lZGFsX2NvbXBsaWFuY2VfaW5kaXZpZHVhbCRDb21wbGlhbmNlUmF0ZSA8NzApKQ0KDQpkZl9tZWRhbF9jb21wbGlhbmNlID0gZGZfbWVkYWxfY2xlYW4gJT4lIGdyb3VwX2J5KGNvbmRpdGlvbikgJT4lIHN1bW1hcmlzZSgnJSBNZWFuIENvbXBsaWFuY2UnID0gc3VtKCFpcy5uYSh0cmlnZ2VyX251bWJlcikpLyhuX2Rpc3RpbmN0KHN1YmplY3Rjb2RlKSAqNDIpKjEwMCkgDQoNCg0KIyBDcmVhdGUgYSB0YWJsZQ0Kc3VtbWFyeV90YWJsZSA9IHN1bW1hcnlfdGFibGUgJT4lIGxlZnRfam9pbihkZl9tZWRhbF9jb21wbGlhbmNlLCBieSA9ICdjb25kaXRpb24nKQ0KcmVtcHN5Yzo6bmljZV90YWJsZShzdW1tYXJ5X3RhYmxlKQ0KYGBgDQoNCiMjIyBUZXN0cyB7LX0NCmBgYHtyfQ0KI2NyZWF0ZSBkYXRhc2V0IHdpdGggb25seSB1bmlxdWUgc3ViamVjdGNvZGUgDQpkZl9tZWRhbF9kaXN0aW5jdCA9IGRmX21lZGFsX2NsZWFuICU+JSBkaXN0aW5jdChzdWJqZWN0Y29kZSwgLmtlZXBfYWxsID0gVFJVRSklPiUgc2VsZWN0KCdzdWJqZWN0Y29kZScsICdjb25kaXRpb24nLCAnYWdlJywgJ2VkdWNhdGlvbicsICdnZW5kZXInKQ0KDQojVGVzdCBmb3IgZGlmZmVyZW5jZXMgYmV0d2VlbiBncm91cHMgDQogICNBZ2UNCiAgZGZfbWVkYWxfZGlzdGluY3QgJT4lIGxtKGFnZSB+IGNvbmRpdGlvbiwgZGF0YT0uKSAlPiUgc3VtbWFyeSgpDQogIA0KICAjZWR1Y2F0aW9uDQogIGNoaXNxLnRlc3QoZGZfbWVkYWxfZGlzdGluY3QkZWR1Y2F0aW9uLCBkZl9tZWRhbF9kaXN0aW5jdCRjb25kaXRpb24pDQogIA0KICAjZ2VuZGVyDQogIGNoaXNxLnRlc3QoZGZfbWVkYWxfZGlzdGluY3QkZ2VuZGVyLCBkZl9tZWRhbF9kaXN0aW5jdCRjb25kaXRpb24pDQpgYGANCg0KIyMjIFBsb3Qgey19DQpgYGB7cn0NCiNDcmVhdGUgYSBHcmFwaCAgDQogICNhZ2UNCiAgYm94cGxvdF9hZ2UgPC0gZ2dwbG90KGRmX21lZGFsX2Rpc3RpbmN0LCBhZXMoeD1jb25kaXRpb24sIHk9YWdlLCBmaWxsPWNvbmRpdGlvbikpICsNCiAgICBnZW9tX2JveHBsb3QoKSArDQogICAgbGFicyh4ID0gJ0NvbmRpdGlvbicsIHkgPSAnQWdlJywgdGFnID0gJ0MnICkgKw0KICAgIGdndGl0bGUoJ0FnZSBwZXIgQ29uZGl0aW9uJykgKw0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHdlc2FuZGVyc29uOjp3ZXNfcGFsZXR0ZShuPTMsIG5hbWU9J0dyYW5kQnVkYXBlc3QyJyApKSAgKw0KICAgIHRoZW1lX2FwYSgpIA0KICBnZ3Bsb3RseShib3hwbG90X2FnZSkNCiAgICANCiAgICAjZWR1Y2F0aW9uDQogICAgcGxvdF9lZHVjIDwtIGdncGxvdChkZl9tZWRhbF9kaXN0aW5jdCwgYWVzKHg9Y29uZGl0aW9uLCBmaWxsID0gZWR1Y2F0aW9uKSkgKw0KICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogICAgICBsYWJzKHg9J0NvbmRpdGlvbicsIHk9ICdQcm9wb3J0aW9uJywgdGFnID0gJ0EnICkgKw0KICAgICAgZ2d0aXRsZSgnRWR1Y2F0aW9uIExldmVsIHBlciBDb25kaXRpb24nKSArDQogICAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNhbmRlcnNvbjo6d2VzX3BhbGV0dGUobj0zLCBuYW1lPSdHcmFuZEJ1ZGFwZXN0MicgKSwgbGFiZWxzID0gYygnTG93JyAsICdNaWRkbGUnICwgJ0hpZ2gnKSwgbmFtZSA9ICdFZHVjYXRpb24nKSAgKw0KICAgICAgdGhlbWVfYXBhKCkgDQogICAgZ2dwbG90bHkocGxvdF9lZHVjKQ0KICAgICAgDQogICAgI0dlbmRlcg0KICAgIHBsb3RfZ2VuZGVyIDwtIGdncGxvdChkZl9tZWRhbF9kaXN0aW5jdCwgYWVzKHg9Y29uZGl0aW9uLCBmaWxsID0gZ2VuZGVyKSkgKw0KICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAnZG9kZ2UnKSArDQogICAgICBsYWJzKHggPSAnQ29uZGl0aW9uJywgeSA9ICdQcm9wb3J0aW9uJywgdGFnID0gJ0InICkgKw0KICAgICAgZ2d0aXRsZSgnR2VuZGVyIHBlciBDb25kaXRpb24nKSArDQogICAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNhbmRlcnNvbjo6d2VzX3BhbGV0dGUobj0zLCBuYW1lPSdHcmFuZEJ1ZGFwZXN0MicgKSwgbGFiZWxzID0gYygnTWFsZScsICdGZW1hbGUnKSwgJ0dlbmRlcicpICArDQogICAgICB0aGVtZV9hcGEoKSANCiAgICBnZ3Bsb3RseShwbG90X2dlbmRlcikNCiAgICAgIA0KICAgICBwbG90X2dlbmRlcl8yIDwtICBnZ3N0YXRzcGxvdDo6Z2diYXJzdGF0cyhkYXRhID0gZGZfbWVkYWxfZGlzdGluY3QsIHggPSBnZW5kZXIsIHkgPSBjb25kaXRpb24pICsNCiAgICAgICAgbGFicyh4ID0gJ0NvbmRpdGlvbicsIHkgPSAnUHJvcG9ydGlvbicsIHRhZyA9ICdCJyApICsNCiAgICAgICAgZ2d0aXRsZSgnR2VuZGVyIHBlciBDb25kaXRpb24nKSArDQogICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHdlc2FuZGVyc29uOjp3ZXNfcGFsZXR0ZShuPTMsIG5hbWU9J0dyYW5kQnVkYXBlc3QyJyApLCBsYWJlbHMgPSBjKCdNYWxlJywgJ0ZlbWFsZScpLCAnR2VuZGVyJykgICsNCiAgICAgICAgdGhlbWVfYXBhKCkgDQogICAgICBnZ3Bsb3RseShwbG90X2dlbmRlcl8yKQ0KDQpnZ3B1YnI6OmdnYXJyYW5nZShwbG90X2VkdWMsIHBsb3RfZ2VuZGVyLCBib3hwbG90X2FnZSwgbnJvdz0yLCBuY29sPTIpICAgIA0KDQojIFN1YnNldCBieSBjb21wbGlhbmNlIHJhdGVzDQpjb21wbGlhbnRfc3VicyA9IGRmX21lZGFsX2NvbXBsaWFuY2VfaW5kaXZpZHVhbCAlPiUgZmlsdGVyKENvbXBsaWFuY2VSYXRlID49IDYwKSANCmRmX21lZGFsX2NsZWFuID0gZGZfbWVkYWxfY2xlYW5bZGZfbWVkYWxfY2xlYW4kc3ViamVjdGNvZGUgJWluJSBjb21wbGlhbnRfc3VicyRzdWJqZWN0Y29kZSAsXQ0KICAgIA0KYGBgDQoNCiMjIFBvc2l0aXZlIE1vb2QgIHsudGFic2V0IC19DQoNCiMjIyBDdXJyZW50IE1vb2Qgey19DQpgYGB7cn0NCmRlc2NyaWJlLmJ5KGRmX21lZGFsX2NsZWFuJHBvc19tb29kLCBncm91cD1kZl9tZWRhbF9jbGVhbiRjb25kaXRpb24pICU+JSByYmluZGxpc3QoKSAlPiUgbXV0YXRlKHZhcnM9YygiY29udCIsICJyZW0iLCAiZGVwIikpDQpgYGANCg0KRGlzdHJpYnV0aW9uDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGE9IGRmX21lZGFsX2NsZWFuLCBhZXMoeD1wb3NfbW9vZCkpICsgZ2VvbV9oaXN0b2dyYW0oKStmYWNldF9ncmlkKGNvbHM9dmFycyhjb25kaXRpb24pKQ0KYGBgIA0KDQpDZW50cmVkIERpc3RyaWJ1dGlvbiANCmBgYHtyfQ0KZ2dwbG90KGRhdGE9IGRmX21lZGFsX2NsZWFuLCBhZXMoeD1wb3NfbW9vZF9jKSkgKyBnZW9tX2hpc3RvZ3JhbSgpK2ZhY2V0X2dyaWQoY29scz12YXJzKGNvbmRpdGlvbikpDQpgYGANCg0KDQojIyMgUmVjZW50IE1lbW9yeSB7LX0NCg0KYGBge3J9DQpkZXNjcmliZS5ieShkZl9tZWRhbF9jbGVhbiRyZWNfbWVtX3Bvc19tb29kLCBncm91cD1kZl9tZWRhbF9jbGVhbiRjb25kaXRpb24pICU+JSByYmluZGxpc3QoKSAlPiUgbXV0YXRlKHZhcnM9YygiY29udCIsICJyZW0iLCAiZGVwIikpDQpgYGANCg0KRGlzdHJpYnV0aW9uDQpgYGB7cn0NCmdncGxvdChkYXRhPSBkZl9tZWRhbF9jbGVhbiwgYWVzKHg9cmVjX21lbV9wb3NfbW9vZCkpICsgZ2VvbV9oaXN0b2dyYW0oKStmYWNldF9ncmlkKGNvbHM9dmFycyhjb25kaXRpb24pKQ0KYGBgDQoNCkNlbnRyZWQgRGlzdHJpYnV0aW9uIA0KYGBge3J9DQpnZ3Bsb3QoZGF0YT0gZGZfbWVkYWxfY2xlYW4sIGFlcyh4PXJlY19tZW1fcG9zX21vb2RfYykpICsgZ2VvbV9oaXN0b2dyYW0oKStmYWNldF9ncmlkKGNvbHM9dmFycyhjb25kaXRpb24pKQ0KYGBgDQoNCg0KIyMjIFJlbW90ZSBNZW1vcnkgey19DQoNCmBgYHtyfQ0KZGVzY3JpYmUuYnkoZGZfbWVkYWxfY2xlYW4kcmVtX21lbV9wb3NfbW9vZCwgZ3JvdXA9ZGZfbWVkYWxfY2xlYW4kY29uZGl0aW9uKSAlPiUgcmJpbmRsaXN0KCkgJT4lIG11dGF0ZSh2YXJzPWMoImNvbnQiLCAicmVtIiwgImRlcCIpKQ0KYGBgDQoNCkRpc3RyaWJ1dGlvbg0KDQpgYGB7cn0NCmdncGxvdChkYXRhPSBkZl9tZWRhbF9jbGVhbiwgYWVzKHg9cmVtX21lbV9wb3NfbW9vZCkpICsgZ2VvbV9oaXN0b2dyYW0oKStmYWNldF9ncmlkKGNvbHM9dmFycyhjb25kaXRpb24pKQ0KYGBgDQoNCkNlbnRyZWQgRGlzdHJpYnV0aW9uIA0KYGBge3J9DQpnZ3Bsb3QoZGF0YT0gZGZfbWVkYWxfY2xlYW4sIGFlcyh4PXJlbV9tZW1fcG9zX21vb2RfYykpICsgZ2VvbV9oaXN0b2dyYW0oKStmYWNldF9ncmlkKGNvbHM9dmFycyhjb25kaXRpb24pKQ0KYGBgDQoNCg0KIyMgTmVnYXRpdmUgTW9vZCB7LSAudGFic2V0fQ0KDQojIyMgQ3VycmVudCBNb29kIHstfQ0KYGBge3J9DQpkZXNjcmliZS5ieShkZl9tZWRhbF9jbGVhbiRuZWdfbW9vZCwgZ3JvdXA9ZGZfbWVkYWxfY2xlYW4kY29uZGl0aW9uKSU+JSByYmluZGxpc3QoKSAlPiUgbXV0YXRlKHZhcnM9YygiY29udCIsICJyZW0iLCAiZGVwIikpDQoNCmBgYA0KDQpEaXN0cmlidXRpb24NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YT0gZGZfbWVkYWxfY2xlYW4sIGFlcyh4PW5lZ19tb29kKSkgKyBnZW9tX2hpc3RvZ3JhbSgpK2ZhY2V0X2dyaWQoY29scz12YXJzKGNvbmRpdGlvbikpDQpgYGANCkNlbnRyZWQgRGlzdHJpYnV0aW9uIA0KYGBge3J9DQpnZ3Bsb3QoZGF0YT0gZGZfbWVkYWxfY2xlYW4sIGFlcyh4PW5lZ19tb29kX2MpKSArIGdlb21faGlzdG9ncmFtKCkrZmFjZXRfZ3JpZChjb2xzPXZhcnMoY29uZGl0aW9uKSkNCmdncGxvdChkYXRhPSBkZl9tZWRhbF9jbGVhbiwgYWVzKHg9bmVnX21vb2RfY3MpKSArIGdlb21faGlzdG9ncmFtKCkrZmFjZXRfZ3JpZChjb2xzPXZhcnMoY29uZGl0aW9uKSkNCmBgYA0KDQoNCiMjIyBSZWNlbnQgTWVtb3J5IHstfQ0KDQpgYGB7cn0NCmRlc2NyaWJlLmJ5KGRmX21lZGFsX2NsZWFuJHJlY19tZW1fbmVnX21vb2QsIGdyb3VwPWRmX21lZGFsX2NsZWFuJGNvbmRpdGlvbikgJT4lIHJiaW5kbGlzdCgpICU+JSBtdXRhdGUodmFycz1jKCJjb250IiwgInJlbSIsICJkZXAiKSkNCmBgYA0KDQpEaXN0cmlidXRpb24NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YT0gZGZfbWVkYWxfY2xlYW4sIGFlcyh4PXJlY19tZW1fbmVnX21vb2QpKSArIGdlb21faGlzdG9ncmFtKCkrZmFjZXRfZ3JpZChjb2xzPXZhcnMoY29uZGl0aW9uKSkNCmBgYA0KQ2VudHJlZCBEaXN0cmlidXRpb24gDQpgYGB7cn0NCmdncGxvdChkYXRhPSBkZl9tZWRhbF9jbGVhbiwgYWVzKHg9cmVjX21lbV9uZWdfbW9vZF9jKSkgKyBnZW9tX2hpc3RvZ3JhbSgpK2ZhY2V0X2dyaWQoY29scz12YXJzKGNvbmRpdGlvbikpDQpgYGANCg0KDQojIyMgUmVtb3RlIE1lbW9yeSB7LX0NCg0KYGBge3J9DQpkZXNjcmliZS5ieShkZl9tZWRhbF9jbGVhbiRyZW1fbWVtX25lZ19tb29kLCBncm91cD1kZl9tZWRhbF9jbGVhbiRjb25kaXRpb24pICU+JSByYmluZGxpc3QoKSAlPiUgbXV0YXRlKHZhcnM9YygiY29udCIsICJyZW0iLCAiZGVwIikpDQpgYGANCg0KRGlzdHJpYnV0aW9uDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGE9IGRmX21lZGFsX2NsZWFuLCBhZXMoeD1yZW1fbWVtX25lZ19tb29kKSkgKyBnZW9tX2hpc3RvZ3JhbSgpK2ZhY2V0X2dyaWQoY29scz12YXJzKGNvbmRpdGlvbikpDQpgYGANCkNlbnRyZWQgRGlzdHJpYnV0aW9uIA0KYGBge3J9DQpnZ3Bsb3QoZGF0YT0gZGZfbWVkYWxfY2xlYW4sIGFlcyh4PXJlbV9tZW1fbmVnX21vb2RfYykpICsgZ2VvbV9oaXN0b2dyYW0oKStmYWNldF9ncmlkKGNvbHM9dmFycyhjb25kaXRpb24pKQ0KYGBgDQoNCg0KIyBNYWluIEVmZmVjdHMgey50YWJzZXR9DQpBIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpcyB3YXMgZG9uZSB0byBsb29rIGF0IHRoZSBkaWZmZXJlbmNlcyBpbiBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgbW9vZCByYXRpbmdzIHBlciBjb25kaXRpb24uDQoNCiMjIExpbmVhciBNaXhlZCBNb2RlbHMgZm9yIFBBIGFuZCBOQQ0KYGBge3J9DQojcG9zaXRpdmUgbW9vZCANCnBvc2l0aXZlX21vZGVsID0gbG1lcihwb3NfbW9vZCB+IGNvbmRpdGlvbiArICgxfHN1YmplY3Rjb2RlKSwgZGF0YSA9IGRmX21lZGFsX2NsZWFuKQ0KDQoNCiNuZWdhdGl2ZSBtb29kDQpuZWdhdGl2ZV9tb2RlbCA9IGxtZXIobmVnX21vb2QgfiBjb25kaXRpb24gKyAoMXxzdWJqZWN0Y29kZSksIGRhdGEgPSBkZl9tZWRhbF9jbGVhbikNCg0KDQoNCmFzaXNfb3V0cHV0KHRhYl9tb2RlbCAocG9zaXRpdmVfbW9kZWwsIG5lZ2F0aXZlX21vZGVsLCANCiAgICAgICAgICAgICAgICAgICAgICBzaG93LnNlID0gVCwgc2hvdy5kZiA9IFQsIHNob3cuYWljID0gVCwgdHJhbnNmb3JtID0gTlVMTCwgIA0KICAgICAgICAgICAgICAgICAgICAgIHNob3cuc3RhdCA9IFQsIHNob3cuc3RkID0gVCwgDQogICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAnQ29uZGl0aW9uIERpZmZlcmVuY2VzIE1vb2QgUmF0aW5nJywgZHYubGFiZWxzID0gYygnUEEgU2NhbGVkJywgICdOQSBTY2FsZWQnKSApJGtuaXRyKQ0KYGBgDQoNCiMjIFBsb3Qgey19DQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQojY3JlYXRlIGJveHBsb3QgZm9yIG5lZ2F0aXZlIGFuZCBwb3NpdGl2ZSBhZmZlY3QgZm9yIGVhY2ggZ3JvdXAgd2l0aCBzaWduaWZpY2FuY2UgbGV2ZWxzIA0KY29tYmluZV9kYXRhID0gZGZfbWVkYWxfY2xlYW4gJT4lDQogIHRpZHlyOjpwaXZvdF9sb25nZXIoY29scz1jKHBvc19tb29kLCBuZWdfbW9vZCksIG5hbWVzX3RvID0gJ21vb2RfdHlwZScsIHZhbHVlc190byA9ICdtb29kX3JhdGluZycpICU+JSANCiAgZHBseXI6Om11dGF0ZShtb29kX3R5cGUgPSBmYWN0b3IobW9vZF90eXBlLCBsZXZlbHMgPSBjKCdwb3NfbW9vZCcgLCAnbmVnX21vb2QnKSkpDQoNCiMgUGxvdA0KbG1fcGxvdCA9IGdncGxvdChjb21iaW5lX2RhdGEsIGFlcyh4PWNvbmRpdGlvbiwgeSA9IG1vb2RfcmF0aW5nLCBmaWxsPSBjb25kaXRpb24pKSArIA0KICBnZW9tX2JveHBsb3QoKSArDQogIGxhYnMoeCA9J0dyb3VwJywgeSA9J01vb2QgKHNjYWxlZCB1bml0cyknICkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoJ2NvbnRyb2wnID0gJ05ldmVyIERlcHJlc3NlZCcsICdyZW1pdHRlZCcgPSAnUmVtaXR0ZWQnLCAnZGVwcmVzc2VkJyA9ICdEZXByZXNzZWQnICkpICsNCiAgZmFjZXRfd3JhcCggfiBtb29kX3R5cGUsIG5jb2wgPTMsIG5yb3cgPSAyLCBsYWJlbGxlciAgPSBsYWJlbGxlcihtb29kX3R5cGUgPSBjKCdwb3NfbW9vZCcgPSAnUG9zaXRpdmUgTW9vZCcsICduZWdfbW9vZCcgID0gJ05lZ2F0aXZlIE1vb2QnKSkpICsNCiAgZ2VvbV9zaWduaWYoY29tcGFyaXNvbnMgPSBsaXN0KGMoJ2NvbnRyb2wnLCAncmVtaXR0ZWQnKSwgYygnY29udHJvbCcgLCAnZGVwcmVzc2VkJyksIGMoJ3JlbWl0dGVkJyAsICdkZXByZXNzZWQnICkpLCBtYXBfc2lnbmlmX2xldmVsID0gVCwgeV9wb3NpdGlvbiA9IGMoMTUsIDEzLCAxMSkpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gd2VzYW5kZXJzb246Ondlc19wYWxldHRlKG49MywgbmFtZT0nR3JhbmRCdWRhcGVzdDInICkpICArDQogIHRoZW1lX2FwYSgpICsgDQogIGd1aWRlcyhmaWxsPUYpDQpnZ3Bsb3RseShsbV9wbG90KQ0KZ2dzYXZlKCdmaWd1cmVfMV9tYWluX2VmZmVjdHMucGRmJywgZHBpID0gMzIwLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA4LCBwYXRoID0gImZpZ3VyZXMvIikNCmBgYA0KDQojIyBGb2xsb3ctVXAgey19DQpgYGB7cn0NCmVtbWVhbnM6OmVtbWVhbnMocG9zaXRpdmVfbW9kZWwsIHBhaXJ3aXNlIH4gY29uZGl0aW9uLCBwYmtydGVzdC5saW1pdCA9IDc4MDAsIGxtZXJUZXN0LmxpbWl0PTc4MDApDQplbW1lYW5zOjplbW1lYW5zKG5lZ2F0aXZlX21vZGVsLCBwYWlyd2lzZSB+IGNvbmRpdGlvbiwgcGJrcnRlc3QubGltaXQgPSA3ODAwLCBsbWVyVGVzdC5saW1pdD03ODAwKQ0KYGBgDQoNCg0KDQojIEh5cG90aGVzaXMgMTogSW5kZXBlbmRlbnQgTW9kZWxzICANCg0KSW4gdGhpcyBzZWN0aW9uIHdlIHRlc3QgdGhlIGZpcnN0IG1vZGVscyBmcm9tIGh5cG90aGVzaXMgMSBhcyBzdGF0ZWQgaW4gdGhlIHByZS1yZWdpc3RyYWl0b24uIFRoZXNlIGFuYWx5c2VzIGxvb2sgYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHJlY2VudCBhbmQgcmVtb3RlIGVtb3Rpb25hbCBtZW1vcnkgZm9yIGJvdGggcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIGFmZmVjdCwgd2hpbGUgYWxzbyBsb29raW5nIGF0IGdyb3VwIGRpZmZlcmVuY2VzIGluIHRoZXNlIHJlbGFpdG9uc2hpcHMgYmFzZWQgb24gZGVwcmVzc2lvbiBzdGF0dXMuIA0KDQpgYGB7cn0NCiMgc2V0IG1vZGVsIGZhbWlsaWVzDQptb2RlbF9mYW1pbGllcyA9IGMoJ2dhdXNzLWxpbmsnLCAiZ2F1c3MtbG9nIiwgJ2dhdXNzLWludicsICdHYW1tYS1saW5rJywgJ0dhbW1hLWxvZycpDQojIGRldGVjdCBjb3JlcyBmb3IgbGF0ZXINCm5jb3JlcyA9IGRldGVjdENvcmVzKCktMQ0KYGBgDQoNCiMjIFBvc2l0aXZlIEFmZmVjdCB7LSAudGFic2V0fQ0KDQpGaXJzdCB3ZSBydW4gdGhlIHBvc2l0aXZlIGFmZmVjdCBtb2RlbHMuIEZvciBlYWNoIG9mIHRoZSByZWNlbnQgYW5kIHJlbW90ZSBtb2RlbHMsIHdlIGNoZWNrIHRoZSBiZXN0IGZpdHRpbmcgbW9kZWwgYXMgc3RhdGVkIGluIHRoZSBwcmUtcmVnaXN0cmF0aW9uIGJhc2VkIG9uIHRoZSBBSUMgYW5kIHRoZSByZXNpZHVhbHMuIFdlIHRoZW4gY2hlY2sgd2hldGhlciBtZWRpYXRpb24gYW5hbHlzZXMgYXJlIHdhcnJhbnRlZCwgYW5kIHJ1biB0aG9zZS4gV2l0aGluIGVhY2ggdGFiIGJlbG93LCB3ZSBwcmVzZW50IHRoZSByZXN1bHRzIGFuZCBzdGVwcyB0YWtlbiwgYXMgd2VsbCBhcyBwb3N0LWhvYyBhbmFseXNlcyB0byBleGFtaW5lIHRoZSBkaXJlY3Rpb25hbGl0eSBvZiB0aGUgZWZmZWN0cy4gDQoNCiMjIyBSZWNlbnQgey0gfQ0KYGBge3J9DQojIE1vZGVsIGVxdWF0aW9uDQpoMV9wb3N0X3JlY2VudF9lcSA9ICJwb3NfbW9vZF9jcyB+IDEgKyBjb25kaXRpb24qcmVjX21lbV9wb3NfbW9vZF9jc19sYWcgKyBnZW5kZXIgKyBhZ2UgKyBlZHVjYXRpb24gKyAoMSArIHJlY19tZW1fcG9zX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSINCg0KIyBzZXQgY2x1c3RlcnMNCmNsID0gbWFrZUNsdXN0ZXIobmNvcmVzKQ0KcmVnaXN0ZXJEb1BhcmFsbGVsKGNsKQ0KDQojIHJ1biBwYXJhbGxlbA0KaDFfcG9zX3JlY2VudF9tb2RlbHMgPSBmb3JlYWNoKGZhbWlseSA9IG1vZGVsX2ZhbWlsaWVzLCAuY29tYmluZSA9ICdjJywgLnBhY2thZ2VzID0gYygnbG1lclRlc3QnKSwgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMV9wb3N0X3JlY2VudF9lcSwgZGZfbWVkYWxfY2xlYW4sIGZhbWlseSkgfQ0Kc3RvcENsdXN0ZXIoY2wpDQoNCiMgcHJpbnQgdGhlIG1vZGVscyBpbnRvIGEgc2luZ2xlIHRhYmxlDQphc2lzX291dHB1dCggdGFiX21vZGVsKGgxX3Bvc19yZWNlbnRfbW9kZWxzLCAgZHYubGFiZWxzID0gbmFtZXMoaDFfcG9zX3JlY2VudF9tb2RlbHMpLCANCiAgICAgICAgICAgICAgICAgICAgICAgc2hvdy5pY2MgPSBULCBzaG93LmFpYyA9IFQsIHRyYW5zZm9ybSA9IE5VTEwsIHNob3cuc2UgPSBULCBkaWdpdHMgPSAzKSRrbml0cikNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkoaDFfcG9zX3JlY2VudF9tb2RlbHNbWzJdXSkNCnBsb3RfZGlhZ25vc3RpY3MoaDFfcG9zX3JlY2VudF9tb2RlbHMpDQpjYXI6OnZpZihoMV9wb3NfcmVjZW50X21vZGVsc1tbMl1dKSAjVmlmcyB3ZXJlIGluc3BlY3RlZCB3aXRob3V0IGludGVyYWN0aW9uIGFuZCBkZWVtZWQgT0sNCmBgYA0KDQojIyMjIyBGb2xsb3ctdXAgey19DQoNCkluIHRoZSBmb2xsb3ctdXAgd2UgbG9vayBhdCB0aGUgcGFpcndpc2UgZGlmZmVyZW5jZXMgaW4gdGhlIHNsb3BlcywgYW5kIHRoZSBpbmRpaXZ1ZHMNCmBgYHtyfQ0KZW1tZWFuczo6ZW10cmVuZHMoaDFfcG9zX3JlY2VudF9tb2RlbHNbWzJdXSwgcGFpcndpc2UgfiBjb25kaXRpb24sIHZhcj0ncmVjX21lbV9wb3NfbW9vZF9jc19sYWcnLCBsbWVyVGVzdC5saW1pdCA9IDM1MDAsIHBia3J0ZXN0LmxpbWl0ID0gMzUwMCApDQpgYGANCg0KYGBge3J9DQojY3JlYXRlIHNlcGFyYXRlIGRhdGFmcmFtZXMgDQpkZl9tZWRhbF9jbGVhbl9jb250cm9sID0gZGZfbWVkYWxfY2xlYW4gJT4lIGZpbHRlcihjb25kaXRpb24gPT0gJ2NvbnRyb2wnKQ0KZGZfbWVkYWxfY2xlYW5fcmVtaXR0ZWQgPSBkZl9tZWRhbF9jbGVhbiAlPiUgZmlsdGVyKGNvbmRpdGlvbiA9PSAncmVtaXR0ZWQnKQ0KZGZfbWVkYWxfY2xlYW5fZGVwcmVzc2VkID0gZGZfbWVkYWxfY2xlYW4gJT4lIGZpbHRlcihjb25kaXRpb24gPT0gJ2RlcHJlc3NlZCcpIA0KDQoNCm0xX3Bvc19yZWNfY29udHJvbCA8LSAgIGxtZXIocG9zX21vb2RfY3MgfiByZWNfbWVtX3Bvc19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiANCiAgICAgICAgICAgICAgICAgICAgICsgKDEgICsgIHJlY19tZW1fcG9zX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9jb250cm9sLA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChjYWxjLmRlcml2cyA9IEYsIG9wdGltaXplcj0nYm9ieXFhJywgb3B0Q3RybD1saXN0KG1heGZ1bj0xZTYpKSkNCg0KbTFfcG9zX3JlY19yZW1pdHRlZCA8LSAgIGxtZXIocG9zX21vb2RfY3MgfiByZWNfbWVtX3Bvc19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiANCiAgICAgICAgICAgICAgICAgICAgICsgKDEgKyByZWNfbWVtX3Bvc19tb29kX2NzX2xhZ3xzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fcmVtaXR0ZWQsDQogICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQptMV9wb3NfcmVjX2RlcHJlc3NlZCA8LSAgIGxtZXIocG9zX21vb2RfY3MgfiByZWNfbWVtX3Bvc19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiANCiAgICAgICAgICAgICAgICAgICAgICsgKDEgICsgcmVjX21lbV9wb3NfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICBkYXRhPWRmX21lZGFsX2NsZWFuX2RlcHJlc3NlZCwNCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCmFzaXNfb3V0cHV0KHRhYl9tb2RlbChtMV9wb3NfcmVjX2NvbnRyb2wsIG0xX3Bvc19yZWNfcmVtaXR0ZWQsIG0xX3Bvc19yZWNfZGVwcmVzc2VkLCBzaG93LnNlID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBkdi5sYWJlbHMgPSBjKCdjb250cm9sJywgJ3JlbWl0dGVkJywgJ2RlcHJlc3NlZCcpKSRrbml0cikgDQpgYGANCg0KDQojIyMgUmVtb3RlIHstfQ0KYGBge3J9DQojIE1vZGVsIGVxdWF0aW9uDQpoMV9wb3NfcmVtb3RlX2VxID0gInBvc19tb29kX2NzIH4gMSArICBjb25kaXRpb24qcmVtX21lbV9wb3NfbW9vZF9jc19sYWcgKyBnZW5kZXIgKyBhZ2UgKyBlZHVjYXRpb24gKyAoMSAgKyByZW1fbWVtX3Bvc19tb29kX2NzX2xhZ3xzdWJqZWN0Y29kZSkiDQoNCiMgc2V0IGNsdXN0ZXJzDQpjbCA9IG1ha2VDbHVzdGVyKG5jb3JlcykNCnJlZ2lzdGVyRG9QYXJhbGxlbChjbCkNCg0KIyBydW4gcGFyYWxsZWwNCmgxX3Bvc19yZW1vdGVfbW9kZWxzID0gZm9yZWFjaChmYW1pbHkgPSBtb2RlbF9mYW1pbGllcywgLmNvbWJpbmUgPSAnYycsIC5wYWNrYWdlcyA9IGMoJ2xtZXJUZXN0JyksICAuZXJyb3JoYW5kbGluZyA9ICJyZW1vdmUiKSAlZG9wYXIlIHsNCiAgZml0X2FsbF9tb2RzKGgxX3Bvc19yZW1vdGVfZXEsIGRmX21lZGFsX2NsZWFuLCBmYW1pbHkpIH0NCnN0b3BDbHVzdGVyKGNsKQ0KDQojIHByaW50IHRoZSBtb2RlbHMgaW50byBhIHNpbmdsZSB0YWJsZQ0KYXNpc19vdXRwdXQoIHRhYl9tb2RlbChoMV9wb3NfcmVtb3RlX21vZGVscywgZHYubGFiZWxzID0gbmFtZXMoaDFfcG9zX3JlbW90ZV9tb2RlbHMpLCANCiAgICAgICAgICAgICAgICAgICAgICAgc2hvdy5pY2MgPSBULCBzaG93LmFpYyA9IFQsIHRyYW5zZm9ybSA9IE5VTEwsIHNob3cuc2UgPSBULCBkaWdpdHMgPSAzKSRrbml0cikNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkoaDFfcG9zX3JlbW90ZV9tb2RlbHNbWzJdXSkNCnBsb3RfZGlhZ25vc3RpY3MoaDFfcG9zX3JlbW90ZV9tb2RlbHMpDQpjYXI6OnZpZihoMV9wb3NfcmVtb3RlX21vZGVsc1tbMl1dKSAjVklGcyB3aXRob3V0IGludGVyYWN0aW9ucyB3ZXJlIGZpbmUNCmBgYA0KDQoNCiMjIyMjIEZvbGxvdy11cCB7LX0NCmBgYHtyfQ0KZW1tZWFuczo6ZW10cmVuZHMoaDFfcG9zX3JlbW90ZV9tb2RlbHNbWzRdXSwgcGFpcndpc2UgfiBjb25kaXRpb24sIHZhcj0ncmVtX21lbV9wb3NfbW9vZF9jc19sYWcnICkNCg0KYGBgDQoNCg0KYGBge3J9DQoNCm0xX3Bvc19yZW1fY29udHJvbCA8LSBsbWVyKHBvc19tb29kX2NzIH4gMSArIHJlbV9tZW1fcG9zX21vb2RfY3NfbGFnICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDEgICsgcmVtX21lbV9wb3NfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fY29udHJvbCwNCiAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQptMV9wb3NfcmVtX3JlbWl0dGVkIDwtIGxtZXIocG9zX21vb2RfY3MgfiAxICsgcmVtX21lbV9wb3NfbW9vZF9jc19sYWcgKyBnZW5kZXIgKyBhZ2UgKyBlZHVjYXRpb24gKyAoMSAgKyByZW1fbWVtX3Bvc19tb29kX2NzX2xhZ3xzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1pdHRlZCwNCiAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChjYWxjLmRlcml2cyA9IEYsIG9wdGltaXplcj0nYm9ieXFhJywgb3B0Q3RybD1saXN0KG1heGZ1bj0xZTYpKSkNCg0KbTFfcG9zX3JlbV9kZXByZXNzZWQgPC0gbG1lcihwb3NfbW9vZF9jcyB+IDEgKyByZW1fbWVtX3Bvc19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiArICgxICArIHJlbV9tZW1fcG9zX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fZGVwcmVzc2VkLA0KICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCmFzaXNfb3V0cHV0KHRhYl9tb2RlbChtMV9wb3NfcmVtX2NvbnRyb2wsIG0xX3Bvc19yZW1fcmVtaXR0ZWQsIG0xX3Bvc19yZW1fZGVwcmVzc2VkLCBzaG93LnNlID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBkdi5sYWJlbHMgPSBjKCdjb250cm9sJywgJ3JlbWl0dGVkJywgJ2RlcHJlc3NlZCcpKSRrbml0cikgDQoNCmBgYA0KDQoNCg0KDQojIyBOZWdhdGl2ZSBBZmZlY3Qgey0gLnRhYnNldH0NCg0KV2UgbmV4dCBydW4gdGhlIG5lZ2F0aXZlIGFmZmVjdCBtb2RlbHMuIEZvciBlYWNoIG9mIHRoZSByZWNlbnQgYW5kIHJlbW90ZSBtb2RlbHMsIHdlIGNoZWNrIHRoZSBiZXN0IGZpdHRpbmcgbW9kZWwgYXMgc3RhdGVkIGluIHRoZSBwcmUtcmVnaXN0cmF0aW9uIGJhc2VkIG9uIHRoZSBBSUMgYW5kIHRoZSByZXNpZHVhbHMuIFdlIHRoZW4gY2hlY2sgd2hldGhlciBtZWRpYXRpb24gYW5hbHlzZXMgYXJlIHdhcnJhbnRlZCwgYW5kIHJ1biB0aG9zZS4gV2l0aGluIGVhY2ggdGFiIGJlbG93LCB3ZSBwcmVzZW50IHRoZSByZXN1bHRzIGFuZCBzdGVwcyB0YWtlbiwgYXMgd2VsbCBhcyBwb3N0LWhvYyBhbmFseXNlcyB0byBleGFtaW5lIHRoZSBkaXJlY3Rpb25hbGl0eSBvZiB0aGUgZWZmZWN0cw0KDQojIyMgUmVjZW50IHstfQ0KYGBge3J9DQojIE1vZGVsIGVxdWF0aW9uDQpoMV9uZWdfcmVjZW50X2VxID0gIm5lZ19tb29kX2NzIH4gY29uZGl0aW9uKnJlY19tZW1fbmVnX21vb2RfY3NfbGFnICArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiArICgxICsgcmVjX21lbV9uZWdfbW9vZF9jc19sYWcgfCBzdWJqZWN0Y29kZSkiDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMV9uZWdfcmVjZW50X21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAuZXJyb3JoYW5kbGluZyA9ICdyZW1vdmUnKSAlZG9wYXIlIHsNCiAgZml0X2FsbF9tb2RzKGgxX25lZ19yZWNlbnRfZXEsIGRmX21lZGFsX2NsZWFuLCBmYW1pbHkpIH0NCnN0b3BDbHVzdGVyKGNsKQ0KDQojIHByaW50IHRoZSBtb2RlbHMgaW50byBhIHNpbmdsZSB0YWJsZQ0KYXNpc19vdXRwdXQoIHRhYl9tb2RlbChoMV9uZWdfcmVjZW50X21vZGVscywgIGR2LmxhYmVscyA9IG5hbWVzKGgxX25lZ19yZWNlbnRfbW9kZWxzKSwgDQogICAgICAgICAgICAgICAgICAgICAgIHNob3cuaWNjID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBzaG93LnNlID0gVCwgZGlnaXRzID0gMykka25pdHIpDQoNCmBgYA0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShoMV9uZWdfcmVjZW50X21vZGVsc1tbNF1dKQ0KcGxvdF9kaWFnbm9zdGljcyhoMV9uZWdfcmVjZW50X21vZGVscykNCmNhcjo6dmlmKGgxX25lZ19yZWNlbnRfbW9kZWxzW1s0XV0pDQpgYGANCg0KDQoNCiMjIyMgRm9sbG93LXVwIHstfQ0KYGBge3J9DQplbW1lYW5zOjplbXRyZW5kcyhoMV9uZWdfcmVjZW50X21vZGVsc1tbNF1dLCBwYWlyd2lzZSB+IGNvbmRpdGlvbiwgdmFyPSdyZWNfbWVtX25lZ19tb29kX2NzX2xhZycgKQ0KDQplbW1lYW5zOjplbW1lYW5zKGgxX25lZ19yZWNlbnRfbW9kZWxzW1s0XV0sIGlkZW50aXR5IH4gcmVjX21lbV9uZWdfbW9vZF9jc19sYWcgfCBjb25kaXRpb24gKQ0KYGBgDQoNCg0KYGBge3J9DQoNCm0xX25lZ19yZWNfY29udHJvbCA8LSBnbG1lcihuZWdfbW9vZF9jcyB+IDEgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiArICgwICArIHJlY19tZW1fbmVnX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9jb250cm9sLA0KICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IEdhbW1hKGxpbms9aWRlbnRpdHkpLA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCm0xX25lZ19yZWNfcmVtaXR0ZWQgPC1nbG1lcihuZWdfbW9vZF9jcyB+IDEgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiArICgwICArIHJlY19tZW1fbmVnX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1pdHRlZCwNCiAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBHYW1tYShsaW5rPWlkZW50aXR5KSwNCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQptMV9uZWdfcmVjX2RlcHJlc3NlZCA8LWdsbWVyKG5lZ19tb29kX2NzIH4gMSArIHJlY19tZW1fbmVnX21vb2RfY3NfbGFnICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDAgICsgcmVjX21lbV9uZWdfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICBkYXRhPWRmX21lZGFsX2NsZWFuX2RlcHJlc3NlZCwNCiAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBHYW1tYShsaW5rPWlkZW50aXR5KSwNCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQphc2lzX291dHB1dCh0YWJfbW9kZWwobTFfbmVnX3JlY19jb250cm9sLCBtMV9uZWdfcmVjX3JlbWl0dGVkLCBtMV9uZWdfcmVjX2RlcHJlc3NlZCwgc2hvdy5zZSA9IFQsIHNob3cuYWljID0gVCwgdHJhbnNmb3JtID0gTlVMTCwgZHYubGFiZWxzID0gYygnY29udHJvbCcsICdyZW1pdHRlZCcsICdkZXByZXNzZWQnKSkka25pdHIpIA0KYGBgDQoNCiMjIyBSZW1vdGUgey19DQpgYGB7cn0NCiMgTW9kZWwgZXF1YXRpb24NCmgxX25lZ19yZW1vdGVfZXEgPSAibmVnX21vb2RfY3MgfiBjb25kaXRpb24qcmVtX21lbV9uZWdfbW9vZF9jc19sYWcgICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDAgICsgcmVtX21lbV9uZWdfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpIg0KDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMV9uZWdfcmVtb3RlX21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMV9uZWdfcmVtb3RlX2VxLCBkZl9tZWRhbF9jbGVhbiwgZmFtaWx5KSB9DQpzdG9wQ2x1c3RlcihjbCkNCg0KIyBwcmludCB0aGUgbW9kZWxzIGludG8gYSBzaW5nbGUgdGFibGUNCmFzaXNfb3V0cHV0KCB0YWJfbW9kZWwoaDFfbmVnX3JlbW90ZV9tb2RlbHMsICAgZHYubGFiZWxzID0gbmFtZXMoaDFfbmVnX3JlbW90ZV9tb2RlbHMpLCANCiAgICAgICAgICAgICAgICAgICAgICAgc2hvdy5pY2MgPSBULCBzaG93LmFpYyA9IFQsIHRyYW5zZm9ybSA9IE5VTEwsIHNob3cuc2UgPSBULCBkaWdpdHMgPSAzKSRrbml0cikNCg0KYGBgDQoNCg0KYGBge3J9DQpzdW1tYXJ5KGgxX25lZ19yZW1vdGVfbW9kZWxzW1syXV0pDQpwbG90X2RpYWdub3N0aWNzKGgxX25lZ19yZW1vdGVfbW9kZWxzKQ0KY2FyOjp2aWYoaDFfbmVnX3JlbW90ZV9tb2RlbHNbWzJdXSkNCmBgYA0KDQoNCiMjIyMgRm9sbG93LXVwIHstfQ0KYGBge3J9DQplbW1lYW5zOjplbXRyZW5kcyhoMV9uZWdfcmVtb3RlX21vZGVsc1tbMl1dLCBwYWlyd2lzZSB+IGNvbmRpdGlvbiwgdmFyPSdyZW1fbWVtX25lZ19tb29kX2NzX2xhZycgKQ0KDQpgYGANCg0KYGBge3J9DQoNCm0xX25lZ19yZW1fY29udHJvbCA8LSAgZ2xtZXIobmVnX21vb2RfY3MgfiAxICsgcmVtX21lbV9uZWdfbW9vZF9jc19sYWcgKyBnZW5kZXIgKyBhZ2UgKyBlZHVjYXRpb24gKyAoMCAgKyByZW1fbWVtX25lZ19tb29kX2NzX2xhZ3xzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fY29udHJvbCwNCiAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBHYW1tYShsaW5rPWlkZW50aXR5KSwNCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQptMV9uZWdfcmVtX3JlbWl0dGVkIDwtIGdsbWVyKG5lZ19tb29kX2NzIH4gMSArIHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDAgICsgcmVtX21lbV9uZWdfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpLA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fcmVtaXR0ZWQsDQogICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gR2FtbWEobGluaz1pZGVudGl0eSksDQogICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGdsbWVyQ29udHJvbChjYWxjLmRlcml2cyA9IEYsIG9wdGltaXplcj0nYm9ieXFhJywgb3B0Q3RybD1saXN0KG1heGZ1bj0xZTYpKSkNCg0KbTFfbmVnX3JlbV9kZXByZXNzZWQgPC0gIGdsbWVyKG5lZ19tb29kX2NzIH4gMSArIHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDAgICsgcmVtX21lbV9uZWdfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpLA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fZGVwcmVzc2VkLA0KICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IEdhbW1hKGxpbms9aWRlbnRpdHkpLA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCmFzaXNfb3V0cHV0KHRhYl9tb2RlbChtMV9uZWdfcmVtX2NvbnRyb2wsIG0xX25lZ19yZW1fcmVtaXR0ZWQsIG0xX25lZ19yZW1fZGVwcmVzc2VkLCBzaG93LnNlID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBkdi5sYWJlbHMgPSBjKCdjb250cm9sJywgJ3JlbWl0dGVkJywgJ2RlcHJlc3NlZCcpKSRrbml0cikgDQpgYGANCg0KDQoNCiMgSHlwb3RoZXNpcyAyOiBDdXJyZW50IEFmZmVjdCBNb2RlcmF0aW9uIA0KDQpGb3IgSDIsIHdlIHdhbnQgdG8gc2VlIHdoZXRoZXIgY3VycmVudCBhZmZlY3RpdmUgc3RhdGVzIG1vZGVyYXRlIHRoZSBhYmlsaXR5IHRvIHJlY2FsbCBwcmV2aW91cyBhZmZlY3RpdmUgc3RhdGVzLiBUaGF0IGlzLCBkbyBjdXJyZW50IG5lZ2F0aXZlIGFmZmVjdCBmZWVsaW5ncyBtb2RlcmF0ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYWZmZWN0IGFuZCByZWNhbGw/IA0KDQpgYGB7cn0NCiNjcmVhdGUgc2VwYXJhdGUgZGF0YWZyYW1lcyBmb3IgZWFjaCBncm91cA0KZGZfbWVkYWxfY2xlYW5fY29udHJvbCA9IGRmX21lZGFsX2NsZWFuICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0nY29udHJvbCcpDQpkZl9tZWRhbF9jbGVhbl9yZW1pdHRlZCA9IGRmX21lZGFsX2NsZWFuICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0ncmVtaXR0ZWQnKQ0KZGZfbWVkYWxfY2xlYW5fZGVwcmVzc2VkID0gZGZfbWVkYWxfY2xlYW4gJT4lIGZpbHRlcihjb25kaXRpb249PSdkZXByZXNzZWQnKQ0KDQojY3JlYXRlIGEgbmV3IGRhdGFmcmFtZSBmb3IgdGhlIHJlbW90ZSB2YXJpYWJsZXMsIHdoZXJlIHRoZSBwYXJ0aWNpcGFudHMgd2l0aCB0aGUgc2luZ3VsYXIgZGF0YXBvaW50cyBhcmUgcmVtb3ZlZCANCmRmX21lZGFsX2NsZWFuX3JlbW90ZSA9IGRmX21lZGFsX2NsZWFuICU+JSBmaWx0ZXIgKCEoc3ViamVjdGNvZGUgPT0gODIyIHwgc3ViamVjdGNvZGUgPT0gOTA2IHwgc3ViamVjdGNvZGUgPT0gNzE3KSkNCg0KI2NyZWF0ZSBzZXBhcmF0ZSBkYXRhZnJhbWVzIHBlciBjb25kaXRpb24gDQpkZl9tZWRhbF9jbGVhbl9yZW1vdGVfY29udHJvbCA9IGRmX21lZGFsX2NsZWFuX3JlbW90ZSAlPiUgZmlsdGVyKGNvbmRpdGlvbj09J2NvbnRyb2wnKQ0KZGZfbWVkYWxfY2xlYW5fcmVtb3RlX3JlbWl0dGVkID0gZGZfbWVkYWxfY2xlYW5fcmVtb3RlICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0ncmVtaXR0ZWQnKQ0KZGZfbWVkYWxfY2xlYW5fcmVtb3RlX2RlcHJlc3NlZCA9IGRmX21lZGFsX2NsZWFuX3JlbW90ZSAlPiUgZmlsdGVyKGNvbmRpdGlvbj09J2RlcHJlc3NlZCcpDQpgYGANCg0KIyMgUG9zaXRpdmUgQWZmZWN0IHstIC50YWJzZXR9DQoNCiMjIyBSZWNlbnQgey19DQpBbiBsbWVyIG1vZGVsIHdhcyBmaXR0ZWQgd2l0aCBnYXVzc2lhbiBpZGVudGl0eSwgbG9nICYgaW52ZXJzZSBhcyB3ZWxsIGFzIEdhbW1hIGxvZywgaW52ZXJzZSwgYW5kIGlkZW50aXR5LiBUaGUgbW9kZWxzLCBob3dldmVyLCB3ZXJlIG5vdCBhIGdvb2QgZml0IGFuZCB0aGUgZ2F1c3NpYW4gaWRlbnRpdHkgbW9kZWwgY29wZWQgd2l0aCBzaW5ndWxhcml0eS4gSGVuY2UsIGEgbm9ybWFsIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHdhcyBmaXR0ZWQuIA0KYGBge3IgZmlnLmhlaWdodD0yMCwgZmlnLndpZHRoPTE1fQ0KaDJfcG9zX3JlY2VudF9lcSA9ICJwb3NfbW9vZF9jcyB+IGNvbmRpdGlvbipyZWNfbWVtX3Bvc19tb29kX2NzX2xhZypwb3NfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDEgKyByZWNfbWVtX3Bvc19tb29kX2NzX2xhZyArIHBvc19tb29kX2NzX2xhZ19yZWN8c3ViamVjdGNvZGUpIg0KDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMl9wb3NfcmVjZW50X21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMl9wb3NfcmVjZW50X2VxLCBkZl9tZWRhbF9jbGVhbiwgZmFtaWx5KSB9DQpzdG9wQ2x1c3RlcihjbCkNCg0KIyBwcmludCB0aGUgbW9kZWxzIGludG8gYSBzaW5nbGUgdGFibGUNCmFzaXNfb3V0cHV0KCB0YWJfbW9kZWwoaDJfcG9zX3JlY2VudF9tb2RlbHMsICBkdi5sYWJlbHMgPSBuYW1lcyhoMl9wb3NfcmVjZW50X21vZGVscyksIA0KICAgICAgICAgICAgICAgICAgICAgICBzaG93LmljYyA9IFQsIHNob3cuYWljID0gVCwgdHJhbnNmb3JtID0gTlVMTCwgc2hvdy5zZSA9IFQsIGRpZ2l0cyA9IDMpJGtuaXRyKQ0KDQoNCmBgYA0KDQpEdWUgdG8gc2luZ3VsYXJpdHkgdGhpcyB3YXMgZGV0ZXJtaW5lZCB0byBiZSB0aGUgYmVzdCBmaXQgZm9yIHRoZSBtb2RkZWwNCg0KYGBge3J9DQpzdW1tYXJ5KGgyX3Bvc19yZWNlbnRfbW9kZWxzW1syXV0pDQpwbG90X2RpYWdub3N0aWNzKGgyX3Bvc19yZWNlbnRfbW9kZWxzKQ0KY2FyOjp2aWYoaDJfcG9zX3JlY2VudF9tb2RlbHNbWzJdXSkNCmBgYA0KDQoNCg0KIyMjIyBGb2xsb3ctdXAgey19DQpgYGB7cn0NCm0yX3Bvc19yZWNfY29udHJvbCA8LSBsbShwb3NfbW9vZF9jcyB+IDEgKyByZWNfbWVtX3Bvc19tb29kX2NzX2xhZypwb3NfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uLA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fY29udHJvbCkNCg0KbTJfcG9zX3JlY19yZW1pdHRlZCA8LSBsbShwb3NfbW9vZF9jcyB+IDEgKyByZWNfbWVtX3Bvc19tb29kX2NzX2xhZypwb3NfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uLA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fcmVtaXR0ZWQpDQoNCm0yX3Bvc19yZWNfZGVwcmVzc2VkIDwtICBsbShwb3NfbW9vZF9jcyB+IDEgKyByZWNfbWVtX3Bvc19tb29kX2NzX2xhZypwb3NfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uLA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fZGVwcmVzc2VkKQ0KDQphc2lzX291dHB1dCh0YWJfbW9kZWwobTJfcG9zX3JlY19jb250cm9sLCBtMl9wb3NfcmVjX3JlbWl0dGVkLCBtMl9wb3NfcmVjX2RlcHJlc3NlZCwgc2hvdy5zZSA9IFQsIHNob3cuYWljID0gVCwgdHJhbnNmb3JtID0gTlVMTCwgZHYubGFiZWxzID0gYygnY29udHJvbCcsICdyZW1pdHRlZCcsICdkZXByZXNzZWQnKSkka25pdHIpDQpgYGANCg0KDQojIyMgUmVtb3RlIHstIC50YWJzZXR9DQoNCkFuIGxtZXIgbW9kZWwgd2FzIGZpdHRlZCB3aXRoIGdhdXNzaWFuIGlkZW50aXR5LCBsb2cgJiBpbnZlcnNlIGFzIHdlbGwgYXMgR2FtbWEgbG9nLCBpbnZlcnNlLCBhbmQgaWRlbnRpdHkuIFRoZSBtb2RlbHMsIGhvd2V2ZXIsIHdlcmUgbm90IGEgZ29vZCBmaXQgYW5kIHRoZSBnYXVzc2lhbiBpZGVudGl0eSBtb2RlbCBjb3BlZCB3aXRoIHNpbmd1bGFyaXR5LiBIZW5jZSwgYSBub3JtYWwgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgd2FzIGZpdHRlZC4gDQpgYGB7cn0NCmgyX3Bvc19yZW1vdGVfZXEgPSAicG9zX21vb2RfY3MgfiBjb25kaXRpb24qcmVtX21lbV9wb3NfbW9vZF9jc19sYWcqcG9zX21vb2RfY3NfbGFnX3JlbSArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiArICgxIHwgc3ViamVjdGNvZGUpIg0KDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMl9wb3NfcmVtb3RlX21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMl9wb3NfcmVtb3RlX2VxLCBkZl9tZWRhbF9jbGVhbiwgZmFtaWx5KSB9DQpzdG9wQ2x1c3RlcihjbCkNCg0KIyBwcmludCB0aGUgbW9kZWxzIGludG8gYSBzaW5nbGUgdGFibGUNCmFzaXNfb3V0cHV0KCB0YWJfbW9kZWwoaDJfcG9zX3JlbW90ZV9tb2RlbHMsICBkdi5sYWJlbHMgPSBuYW1lcyhoMl9wb3NfcmVtb3RlX21vZGVscyksIA0KICAgICAgICAgICAgICAgICAgICAgICBzaG93LmljYyA9IFQsIHNob3cuYWljID0gVCwgdHJhbnNmb3JtID0gTlVMTCwgc2hvdy5zZSA9IFQsIGRpZ2l0cyA9IDMpJGtuaXRyKQ0KDQoNCmBgYA0KDQoNCkR1ZSB0byBzaW5ndWxhcml0eSBhIHJlZ3VsYXIgbGluZWFyIG1vZGVsIHdhcyBmaXR0ZWQuDQpgYGB7cn0NCnN1bW1hcnkoaDJfcG9zX3JlbW90ZV9tb2RlbHNbWzJdXSkNCnBsb3RfZGlhZ25vc3RpY3MoaDJfcG9zX3JlbW90ZV9tb2RlbHMpDQpjYXI6OnZpZihoMl9wb3NfcmVtb3RlX21vZGVsc1tbMl1dKQ0KDQpgYGANCg0KDQojIyMjIEZvbGxvdy11cCB7LX0NCmBgYHtyfQ0KDQptMl9wb3NfcmVtX2NvbnRyb2wgPC0gbG0ocG9zX21vb2RfY3MgfiByZW1fbWVtX3Bvc19tb29kX2NzX2xhZypwb3NfbW9vZF9jc19sYWdfcmVtICArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbiwgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1vdGVfY29udHJvbCkNCg0KbTJfcG9zX3JlbV9yZW1pdHRlZCA8LSBsbShwb3NfbW9vZF9jcyB+IHJlbV9tZW1fcG9zX21vb2RfY3NfbGFnKnBvc19tb29kX2NzX2xhZ19yZW0gICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uLCAgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1vdGVfcmVtaXR0ZWQpDQoNCm0yX3Bvc19yZW1fZGVwcmVzc2VkIDwtICBsbShwb3NfbW9vZF9jcyB+IHJlbV9tZW1fcG9zX21vb2RfY3NfbGFnKnBvc19tb29kX2NzX2xhZ19yZW0gICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uLCANCiAgICAgICAgICAgICAgICAgICBkYXRhPWRmX21lZGFsX2NsZWFuX3JlbW90ZV9kZXByZXNzZWQpDQoNCmFzaXNfb3V0cHV0KHRhYl9tb2RlbChtMl9wb3NfcmVtX2NvbnRyb2wsIG0yX3Bvc19yZW1fcmVtaXR0ZWQsIG0yX3Bvc19yZW1fZGVwcmVzc2VkLCBzaG93LnNlID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBkdi5sYWJlbHMgPSBjKCdjb250cm9sJywgJ3JlbWl0dGVkJywgJ2RlcHJlc3NlZCcpKSRrbml0cikgDQpgYGANCg0KDQoNCiMjIE5lZ2F0aXZlIEFmZmVjdCB7LSAudGFic2V0fQ0KDQojIyMgIFJlY2VudCB7LX0NCmBgYHtyfQ0KaDJfbmVnX3JlY2VudF9lcSA9ICJuZWdfbW9vZF9jcyB+IGNvbmRpdGlvbipyZWNfbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDEgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyArIG5lZ19tb29kX2NzX2xhZ19yZWN8c3ViamVjdGNvZGUpIg0KDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMl9uZWdfcmVjZW50X21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMl9uZWdfcmVjZW50X2VxLCBkZl9tZWRhbF9jbGVhbiwgZmFtaWx5KSB9DQpzdG9wQ2x1c3RlcihjbCkNCg0KIyBwcmludCB0aGUgbW9kZWxzIGludG8gYSBzaW5nbGUgdGFibGUNCmFzaXNfb3V0cHV0KCB0YWJfbW9kZWwoaDJfbmVnX3JlY2VudF9tb2RlbHMsIGR2LmxhYmVscyA9IG5hbWVzKGgyX25lZ19yZWNlbnRfbW9kZWxzKSwgDQogICAgICAgICAgICAgICAgICAgICAgIHNob3cuaWNjID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBzaG93LnNlID0gVCwgZGlnaXRzID0gMykka25pdHIpDQoNCmBgYA0KDQpDaGVjayBGaW5hbCBNb2RlbA0KYGBge3IgfQ0Kc3VtbWFyeShoMl9uZWdfcmVjZW50X21vZGVsc1tbNF1dKQ0KcGxvdF9kaWFnbm9zdGljcyhoMl9uZWdfcmVjZW50X21vZGVscykgDQpjYXI6OnZpZihoMl9uZWdfcmVjZW50X21vZGVsc1tbNF1dKQ0KDQpgYGANCg0KDQoNCg0KIyMjIyBGb2xsb3ctdXAgey19DQpgYGB7cn0NCg0KbTJfbmVnX3JlY19jb250cm9sIDwtIGdsbWVyKG5lZ19tb29kX2NzIH4gcmVjX21lbV9uZWdfbW9vZF9jc19sYWcqbmVnX21vb2RfY3NfbGFnX3JlYyArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSAgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyB8IHN1YmplY3Rjb2RlKSArICgxICsgIG5lZ19tb29kX2NzX2xhZ19yZWN8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICBkYXRhPWRmX21lZGFsX2NsZWFuX2NvbnRyb2wsDQogICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gR2FtbWEobGluaz1pZGVudGl0eSksIA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCm0yX25lZ19yZWNfcmVtaXR0ZWQgPC0gZ2xtZXIobmVnX21vb2RfY3MgfiByZWNfbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSAgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyB8IHN1YmplY3Rjb2RlKSArICgxICsgIG5lZ19tb29kX2NzX2xhZ19yZWN8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICBkYXRhPWRmX21lZGFsX2NsZWFuX3JlbWl0dGVkLA0KICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IEdhbW1hKGxpbms9aWRlbnRpdHkpLCANCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQptMl9uZWdfcmVjX2RlcHJlc3NlZCA8LSAgZ2xtZXIobmVnX21vb2RfY3MgfiByZWNfbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVjICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSAgKyByZWNfbWVtX25lZ19tb29kX2NzX2xhZyB8IHN1YmplY3Rjb2RlKSArICgxICsgIG5lZ19tb29kX2NzX2xhZ19yZWN8c3ViamVjdGNvZGUpLCAgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9kZXByZXNzZWQsDQogICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gR2FtbWEobGluaz1pZGVudGl0eSksIA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCmFzaXNfb3V0cHV0KHRhYl9tb2RlbChtMl9uZWdfcmVjX2NvbnRyb2wsIG0yX25lZ19yZWNfcmVtaXR0ZWQsIG0yX25lZ19yZWNfZGVwcmVzc2VkLCBzaG93LnNlID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBkdi5sYWJlbHMgPSBjKCdjb250cm9sJywgJ3JlbWl0dGVkJywgJ2RlcHJlc3NlZCcpKSRrbml0cikgDQpgYGANCg0KDQoNCg0KIyMjIFJlbW90ZSB7LX0NCmBgYHtyfQ0KaDJfbmVnX3JlbW90ZV9lcSA9ICJuZWdfbW9vZF9jcyB+IGNvbmRpdGlvbipyZW1fbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVtICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uICsgKDEgKyByZW1fbWVtX25lZ19tb29kX2NzX2xhZyArIG5lZ19tb29kX2NzX2xhZ19yZW18c3ViamVjdGNvZGUpIg0KDQojIHNldCBjbHVzdGVycw0KY2wgPSBtYWtlQ2x1c3RlcihuY29yZXMpDQpyZWdpc3RlckRvUGFyYWxsZWwoY2wpDQoNCiMgcnVuIHBhcmFsbGVsDQpoMl9uZWdfcmVtb3RlX21vZGVscyA9IGZvcmVhY2goZmFtaWx5ID0gbW9kZWxfZmFtaWxpZXMsIC5jb21iaW5lID0gJ2MnLCAucGFja2FnZXMgPSBjKCdsbWVyVGVzdCcpLCAgLmVycm9yaGFuZGxpbmcgPSAicmVtb3ZlIikgJWRvcGFyJSB7DQogIGZpdF9hbGxfbW9kcyhoMl9uZWdfcmVtb3RlX2VxLCBkZl9tZWRhbF9jbGVhbiwgZmFtaWx5KSB9DQpzdG9wQ2x1c3RlcihjbCkNCg0KIyBwcmludCB0aGUgbW9kZWxzIGludG8gYSBzaW5nbGUgdGFibGUNCmFzaXNfb3V0cHV0KCB0YWJfbW9kZWwoaDJfbmVnX3JlbW90ZV9tb2RlbHMsIGR2LmxhYmVscyA9IG5hbWVzKGgyX25lZ19yZW1vdGVfbW9kZWxzKSwgDQogICAgICAgICAgICAgICAgICAgICAgIHNob3cuaWNjID0gVCwgc2hvdy5haWMgPSBULCB0cmFuc2Zvcm0gPSBOVUxMLCBzaG93LnNlID0gVCwgZGlnaXRzID0gMykka25pdHIpDQoNCmBgYA0KDQpDaGVjayBGaW5hbCBNb2RlbA0KYGBge3J9DQpzdW1tYXJ5KGgyX25lZ19yZW1vdGVfbW9kZWxzW1s0XV0pDQpwbG90X2RpYWdub3N0aWNzKGgyX25lZ19yZW1vdGVfbW9kZWxzKQ0KY2FyOjp2aWYoaDJfbmVnX3JlbW90ZV9tb2RlbHNbWzRdXSkNCmBgYA0KDQoNCg0KDQojIyMjIEZvbGxvdy11cCB7LX0NCmBgYHtyfQ0KDQptMl9uZWdfcmVtX2NvbnRyb2wgPC0gZ2xtZXIobmVnX21vb2RfY3MgfiByZW1fbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVtICArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgKDEgICsgIHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSArICgxICsgbmVnX21vb2RfY3NfbGFnX3JlbXxzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfY2xlYW5fcmVtb3RlX2NvbnRyb2wsDQogICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gR2FtbWEobGluaz1pZGVudGl0eSksIA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCm0yX25lZ19yZW1fcmVtaXR0ZWQgPC0gZ2xtZXIobmVnX21vb2RfY3MgfiByZW1fbWVtX25lZ19tb29kX2NzX2xhZypuZWdfbW9vZF9jc19sYWdfcmVtICArIGdlbmRlciArIGFnZSArIGVkdWNhdGlvbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgKDEgICsgIHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnfHN1YmplY3Rjb2RlKSArICgxICsgbmVnX21vb2RfY3NfbGFnX3JlbXxzdWJqZWN0Y29kZSksDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1vdGVfcmVtaXR0ZWQsDQogICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gR2FtbWEobGluaz1pZGVudGl0eSksIA0KICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSkpDQoNCm0yX25lZ19yZW1fZGVwcmVzc2VkIDwtICBnbG1lcihuZWdfbW9vZF9jcyB+IHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnKm5lZ19tb29kX2NzX2xhZ19yZW0gICsgZ2VuZGVyICsgYWdlICsgZWR1Y2F0aW9uDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKyAoMSAgKyAgcmVtX21lbV9uZWdfbW9vZF9jc19sYWd8c3ViamVjdGNvZGUpICsgKDEgKyBuZWdfbW9vZF9jc19sYWdfcmVtfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgZGF0YT1kZl9tZWRhbF9jbGVhbl9yZW1vdGVfZGVwcmVzc2VkLA0KICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IEdhbW1hKGxpbms9aWRlbnRpdHkpLCANCiAgICAgICAgICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKGNhbGMuZGVyaXZzID0gRiwgb3B0aW1pemVyPSdib2J5cWEnLCBvcHRDdHJsPWxpc3QobWF4ZnVuPTFlNikpKQ0KDQphc2lzX291dHB1dCh0YWJfbW9kZWwobTJfbmVnX3JlbV9jb250cm9sLCBtMl9uZWdfcmVtX3JlbWl0dGVkLCBtMl9uZWdfcmVtX2RlcHJlc3NlZCwgc2hvdy5zZSA9IFQsIHNob3cuYWljID0gVCwgdHJhbnNmb3JtID0gTlVMTCwgZHYubGFiZWxzID0gYygnY29udHJvbCcsICdyZW1pdHRlZCcsICdkZXByZXNzZWQnKSkka25pdHIpIA0KYGBgDQoNCg0KIyBFeHBsb3JhdG9yeSBBbmFseXNlcw0KDQojIyBNZWRpYXRpb24gTW9kZWxzIHsudGFic2V0fQ0KDQpGb2xsb3dpbmcgdGhlIHRlc3RzIHdlIHJhbiBmb3IgaHlwb3RoZXNpcyAxLCB3ZSB3b3VsZCBhbHNvIGxpa2UgdG8gc2VlIHdoZXRoZXIgb3Igbm90IG1lZGlhdGlvbiBlZmZlY3RzIGV4aXN0LiANCg0KIyMjIFJlY1BBIHstfQ0KDQpgYGB7cn0NCg0KI2NyZWF0ZSBhIG5ldyBkYXRhZnJhbWUgZm9yIHRoZSByZW1vdGUgdmFyaWFibGVzLCB3aGVyZSB0aGUgcGFydGljaXBhbnRzIHdpdGggdGhlIHNpbmd1bGFyIGRhdGFwb2ludHMgYXJlIHJlbW92ZWQgDQpkZl9tZWRhbF9tb2RlcmF0aW9uID0gIGRmX21lZGFsX2NsZWFuICU+JSANCiAgZmlsdGVyICghKHN1YmplY3Rjb2RlID09IDgyMiB8IHN1YmplY3Rjb2RlID09IDkwNiB8IHN1YmplY3Rjb2RlID09IDcxNykpICU+JSANCiAgZmlsdGVyKCEoaXMubmEocG9zX21vb2QpIHwgaXMubmEocmVjX21lbV9wb3NfbW9vZF9sYWcpKSkgDQoNCiMgbWVkIG1vZGVsDQptZWRfZml0X2gxX3Bvc19yZWMgPC0gbG1lNDo6bG1lcihyZWNfbWVtX3Bvc19tb29kX2xhZyB+IGNvbmRpdGlvbl9kdW1teSArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZSArIGdlbmRlciArIGVkdWNhdGlvbiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSB8c3ViamVjdGNvZGUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX21lZGFsX21vZGVyYXRpb24pDQojIGZ1bGwgbW9kZWwNCm91dF9maXRfaDFfcG9zX3JlYyA8LWxtZTQ6OmxtZXIocG9zX21vb2QgfiBjb25kaXRpb25fZHVtbXkgKyByZWNfbWVtX3Bvc19tb29kX2xhZyArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdlICsgZ2VuZGVyICtlZHVjYXRpb24gKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxICsgcmVjX21lbV9wb3NfbW9vZF9sYWcgfHN1YmplY3Rjb2RlKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl9tZWRhbF9tb2RlcmF0aW9uKQ0KDQojbWVkaWF0aW9uIGFuYWx5c2lzIGZvciBjb250cm9sIGFuZCBkZXByZXNzZWQNCm1lZF9wb3NfcmVjX2RlcCA8LSBtZWRpYXRpb246Om1lZGlhdGUobWVkX2ZpdF9oMV9wb3NfcmVjLCBvdXRfZml0X2gxX3Bvc19yZWMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZWF0ID0gJ2NvbmRpdGlvbl9kdW1teScgLCBjb250cm9sLnZhbHVlID0gMSwgdHJlYXQudmFsdWUgPSAzICwgIG1lZGlhdG9yID0gJ3JlY19tZW1fcG9zX21vb2RfbGFnJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXM9MTAwMDApDQpzdW1tYXJ5KG1lZF9wb3NfcmVjX2RlcCkNCg0KYGBgDQoNCg0KIyMjIFJlbU5BIHstfQ0KYGBge3J9DQpkZl9tZWRhbF9tb2RlcmF0aW9uID0gZGZfbWVkYWxfY2xlYW5fcmVtb3RlICU+JSBmaWx0ZXIoIShpcy5uYShuZWdfbW9vZCkgfCBpcy5uYShyZWNfbWVtX25lZ19tb29kX2xhZykpKSANCg0KIyBtZWQgbW9kZWwNCm1lZF9maXRfaDFfbmVnX3JlYyA8LSBsbWU0OjpsbWVyKHJlY19tZW1fbmVnX21vb2RfbGFnIH4gY29uZGl0aW9uX2R1bW15ICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdlICsgZ2VuZGVyICsgZWR1Y2F0aW9uICsgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSB8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkZl9tZWRhbF9tb2RlcmF0aW9uKQ0KIyBmdWxsIG1vZGVsDQpvdXRfZml0X2gxX25lZ19yZWMgPC0gbG1lNDo6bG1lcihuZWdfbW9vZCB+IGNvbmRpdGlvbl9kdW1teSArIHJlY19tZW1fbmVnX21vb2RfbGFnICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2UgKyBnZW5kZXIgK2VkdWNhdGlvbiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxICsgcmVjX21lbV9uZWdfbW9vZF9sYWd8c3ViamVjdGNvZGUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRmX21lZGFsX21vZGVyYXRpb24pDQoNCg0KI21lZGlhdGlvbiBhbmFseXNpcyBmb3IgY29udHJvbCBhbmQgcmVtaXR0ZWQNCnN1bW1hcnkobWVkaWF0aW9uOjptZWRpYXRlKG1lZF9maXRfaDFfbmVnX3JlYywgb3V0X2ZpdF9oMV9uZWdfcmVjLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZWF0ID0gJ2NvbmRpdGlvbl9kdW1teScgLCBtZWRpYXRvciA9ICdyZWNfbWVtX25lZ19tb29kX2xhZycsIGNvbnRyb2wudmFsdWUgPSAxLCB0cmVhdC52YWx1ZSA9IDIgLCAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltcz0xMDAwMCkpDQoNCiNtZWRpYXRpb24gYW5hbHlzaXMgZm9yIGNvbnRyb2wgYW5kIGRlcHJlc3NlZA0Kc3VtbWFyeShtZWRpYXRpb246Om1lZGlhdGUobWVkX2ZpdF9oMV9uZWdfcmVjLCBvdXRfZml0X2gxX25lZ19yZWMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJlYXQgPSAnY29uZGl0aW9uX2R1bW15JyAsICBtZWRpYXRvciA9ICdyZWNfbWVtX25lZ19tb29kX2xhZycsIGNvbnRyb2wudmFsdWUgPSAxLCB0cmVhdC52YWx1ZSA9IDMgLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltcz0xMDAwMCkpDQoNCmBgYA0KDQojIyBNb2RlcmF0ZWQgTWVkaWF0aW9uIHsudGFic2V0fQ0KDQojIyMgUmVtUEEtQ3VyclBBIHstfQ0KYGBge3J9DQoNCmRmX21lZGFsX21vZGVyYXRpb24gPSBkZl9tZWRhbF9jbGVhbl9yZW1vdGUgJT4lIA0KICBmaWx0ZXIoIShpcy5uYShwb3NfbW9vZCkgfCBpcy5uYShyZW1fbWVtX3Bvc19tb29kX2xhZykpKSANCg0KI21lZGlhdGlvbiBmaXJzdA0KbWVkX2ZpdF9oMl9wb3NfcmVtIDwtIGxtZTQ6OmxtZXIocmVtX21lbV9wb3NfbW9vZF9sYWcgfiBjb25kaXRpb25fZHVtbXkgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdlICsgZ2VuZGVyICsgZWR1Y2F0aW9uICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxIHxzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9ZGZfbWVkYWxfbW9kZXJhdGlvbikNCiMgZnVsbCBtb2RlbA0Kb3V0X2ZpdF9oMl9wb3NfcmVtIDwtbG1lNDo6bG1lcihwb3NfbW9vZCB+IGNvbmRpdGlvbl9kdW1teSArIHJlbV9tZW1fcG9zX21vb2RfbGFnIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIGFnZSArIGdlbmRlciArZWR1Y2F0aW9uICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSArIHJlbV9tZW1fcG9zX21vb2RfbGFnIHxzdWJqZWN0Y29kZSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfbW9kZXJhdGlvbikNCg0KDQojbWVkaWF0aW9uIGFuYWx5c2lzIGZvciBjb250cm9sIGFuZCByZW1pdHRlZA0KbWVkX3Bvc19yZW1fcmVtIDwtIG1lZGlhdGlvbjo6bWVkaWF0ZShtZWRfZml0X2gyX3Bvc19yZW0sIG91dF9maXRfaDJfcG9zX3JlbSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZWF0ID0gJ2NvbmRpdGlvbl9kdW1teScgLCBjb250cm9sLnZhbHVlID0gMSwgdHJlYXQudmFsdWUgPSAyICwgIG1lZGlhdG9yID0gJ3JlbV9tZW1fcG9zX21vb2RfbGFnJykNCnN1bW1hcnkobWVkX3Bvc19yZW1fcmVtKQ0KDQojY3JlYXRlIG5ldyBkYXRhZnJhbWVzIHdpdGggb25seSBjb250cm9sIHJlbWl0dGVkIGFuZCBvbmx5IGNvbnRyb2wgZGVwcmVzc2VkDQpkZl9tZWRhbF9jb25fcmVtID0gZGZfbWVkYWxfY2xlYW4gJT4lIGZpbHRlcihjb25kaXRpb249PSdjb250cm9sJyB8IGNvbmRpdGlvbiA9PSAncmVtaXR0ZWQnKQ0KZGZfbWVkYWxfY29uX2RlcCA9IGRmX21lZGFsX2NsZWFuICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0nY29udHJvbCcgfCBjb25kaXRpb24gPT0gJ2RlcHJlc3NlZCcpDQoNCiNyZW1pdHRlZCBncm91cA0KZGZfbWVkYWxfY29uX3JlbSRjb25kaXRpb25fZHVtbXkgPSBidWlsZF9jb250cmFzdChkZl9tZWRhbF9jb25fcmVtJGNvbmRpdGlvbiwgJ2NvbnRyb2wnLCAncmVtaXR0ZWQnKQ0KbWVkX2gyX3Bvc19yZW1fcmVtIDwtIG1kdF9tb2RlcmF0ZWQoZGF0YSA9IGRmX21lZGFsX2Nvbl9yZW0sIElWID1jb25kaXRpb25fZHVtbXksIERWID0gcG9zX21vb2QsIE0gPSByZW1fbWVtX3Bvc19tb29kX2xhZywgTW9kID0gcG9zX21vb2RfbGFnX3JlbSkgDQpyYmluZGxpc3QobWVkX2gyX3Bvc19yZW1fcmVtJHBhdGhzLCBpZGNvbCA9IFQpDQoNCmBgYA0KDQojIyMgUmVtTkEgLSBDdXJyTkEgey19DQpgYGB7ciBwYWdlZC5wcmludD1UUlVFfQ0KZGZfbWVkYWxfbW9kZXJhdGlvbiA9IGRmX21lZGFsX2NsZWFuX3JlbW90ZSAlPiUgZmlsdGVyKCEoaXMubmEobmVnX21vb2QpIHwgaXMubmEocmVtX21lbV9uZWdfbW9vZF9sYWcpKSkgDQoNCiNtZWRpYXRpb24gZmlyc3QNCm1lZF9maXRfaDJfbmVnX3JlbSA8LSBsbWU0OjpsbWVyKHJlbV9tZW1fbmVnX21vb2RfbGFnIH4gY29uZGl0aW9uX2R1bW15ICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdlICsgZ2VuZGVyICsgZWR1Y2F0aW9uICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDEgfHN1YmplY3Rjb2RlKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChjYWxjLmRlcml2cyA9IEYsIG9wdGltaXplcj0nYm9ieXFhJywgb3B0Q3RybD1saXN0KG1heGZ1bj0xZTYpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPWRmX21lZGFsX21vZGVyYXRpb24pDQoNCm91dF9maXRfaDJfbmVnX3JlbSA8LWxtZTQ6OmxtZXIobmVnX21vb2QgfiBjb25kaXRpb25fZHVtbXkgKyByZW1fbWVtX25lZ19tb29kX2xhZyArDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWdlICsgZ2VuZGVyICsgZWR1Y2F0aW9uICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSArIHJlbV9tZW1fbmVnX21vb2RfbGFnIHxzdWJqZWN0Y29kZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2woY2FsYy5kZXJpdnMgPSBGLCBvcHRpbWl6ZXI9J2JvYnlxYScsIG9wdEN0cmw9bGlzdChtYXhmdW49MWU2KSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZGZfbWVkYWxfbW9kZXJhdGlvbikNCg0KI21lZGlhdGlvbiBhbmFseXNpcyBmb3IgY29udHJvbCBhbmQgZGVwcmVzc2VkDQptZWRfbmVnX3JlbV9kZXAgPC0gbWVkaWF0aW9uOjptZWRpYXRlKG1lZF9maXRfaDJfbmVnX3JlbSwgb3V0X2ZpdF9oMl9uZWdfcmVtLCAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhdG9yID0gJ3JlbV9tZW1fbmVnX21vb2RfbGFnJywgIHRyZWF0ID0gJ2NvbmRpdGlvbl9kdW1teScgLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbC52YWx1ZSA9IDEsIHRyZWF0LnZhbHVlID0gMyAsIHNpbXM9MTAwMDApIA0Kc3VtbWFyeShtZWRfbmVnX3JlbV9kZXApDQoNCiNtZWRpYXRpb24gYW5hbHlzaXMgZm9yIGNvbnRyb2wgYW5kIHJlbWl0dGVkDQptZWRfbmVnX3JlbV9yZW0gPC0gbWVkaWF0aW9uOjptZWRpYXRlKG1lZF9maXRfaDJfbmVnX3JlbSwgb3V0X2ZpdF9oMl9uZWdfcmVtLCB0cmVhdCA9ICdjb25kaXRpb25fZHVtbXknICwgY29udHJvbC52YWx1ZSA9IDEsIHRyZWF0LnZhbHVlID0gMiAsICBtZWRpYXRvciA9ICdyZW1fbWVtX25lZ19tb29kX2xhZycsIHNpbXM9MTAwMDApIA0Kc3VtbWFyeShtZWRfbmVnX3JlbV9yZW0pDQoNCiNjcmVhdGUgbmV3IGRhdGFmcmFtZXMgd2l0aCBvbmx5IGNvbnRyb2wgcmVtaXR0ZWQgYW5kIG9ubHkgY29udHJvbCBkZXByZXNzZWQNCmRmX21lZGFsX2Nvbl9yZW0gPSBkZl9tZWRhbF9jbGVhbiAlPiUgZmlsdGVyKGNvbmRpdGlvbj09J2NvbnRyb2wnIHwgY29uZGl0aW9uID09ICdyZW1pdHRlZCcpDQpkZl9tZWRhbF9jb25fZGVwID0gZGZfbWVkYWxfY2xlYW4gJT4lIGZpbHRlcihjb25kaXRpb249PSdjb250cm9sJyB8IGNvbmRpdGlvbiA9PSAnZGVwcmVzc2VkJykNCg0KI3JlbWl0dGVkIGdyb3VwDQpkZl9tZWRhbF9jb25fcmVtJGNvbmRpdGlvbl9kdW1teSA9IGJ1aWxkX2NvbnRyYXN0KGRmX21lZGFsX2Nvbl9yZW0kY29uZGl0aW9uLCAnY29udHJvbCcsICdyZW1pdHRlZCcpDQptZWRfaDJfbmVnX3JlbV9yZW0gPC0gbWR0X21vZGVyYXRlZChkYXRhID0gZGZfbWVkYWxfY29uX3JlbSwgSVYgPSBjb25kaXRpb25fZHVtbXksIERWID0gbmVnX21vb2QsIE0gPSByZW1fbWVtX25lZ19tb29kX2xhZywgTW9kID0gbmVnX21vb2RfbGFnX3JlbSkgDQpyYmluZGxpc3QobWVkX2gyX25lZ19yZW1fcmVtJHBhdGhzLCBpZGNvbCA9IFQpDQoNCiNkZXByZXNzZWQgZ3JvdXANCmRmX21lZGFsX2Nvbl9kZXAkY29uZGl0aW9uX2R1bW15ID0gYnVpbGRfY29udHJhc3QoZGZfbWVkYWxfY29uX2RlcCRjb25kaXRpb24sICdjb250cm9sJywgJ2RlcHJlc3NlZCcpDQptZWRfaDJfbmVnX3JlbV9kZXAgPC0gbWR0X21vZGVyYXRlZChkYXRhID0gZGZfbWVkYWxfY29uX2RlcCwgSVYgPSBjb25kaXRpb25fZHVtbXksIERWID0gbmVnX21vb2QsIE0gPSByZW1fbWVtX25lZ19tb29kX2xhZywgTW9kID0gbmVnX21vb2RfbGFnX3JlbSkgDQpyYmluZGxpc3QobWVkX2gyX25lZ19yZW1fZGVwJHBhdGhzLGlkY29sID0gVCkNCiAgDQpgYGANCg0KIyMgQ29udGV4dA0KDQpgYGB7cn0NCmFzaXNfb3V0cHV0KHRhYl9tb2RlbCggKGxtZXIocG9zX21vb2RfY3MgfiByZWNfbWVtX3Bvc19tb29kX2NzX2xhZypjb250ZXh0X2xvY2F0aW9uICsgKDEgIHwgc3ViamVjdGNvZGUpLCBkYXRhID0gZGZfbWVkYWxfY2xlYW4pKSwgDQogICAgICAgICAgIChsbWVyKHBvc19tb29kX2NzIH4gcmVtX21lbV9wb3NfbW9vZF9jc19sYWcqY29udGV4dF9sb2NhdGlvbiArICgxICB8IHN1YmplY3Rjb2RlKSwgZGF0YSA9IGRmX21lZGFsX2NsZWFuKSksDQogICAgICAgICAgICAobG1lcihuZWdfbW9vZF9jcyB+IHJlbV9tZW1fbmVnX21vb2RfY3NfbGFnKmNvbnRleHRfbG9jYXRpb24gKyAoMSAgfCBzdWJqZWN0Y29kZSksIGRhdGEgPSBkZl9tZWRhbF9jbGVhbikpLA0KICAgICAgICAgICAgIChsbWVyKG5lZ19tb29kX2NzIH4gcmVtX21lbV9uZWdfbW9vZF9jc19sYWcqY29udGV4dF9sb2NhdGlvbiArICgxICB8IHN1YmplY3Rjb2RlKSwgZGF0YSA9IGRmX21lZGFsX2NsZWFuKSkpJGtuaXRyKQ0KDQpgYGANCg0KIyMgU1JFVA0KDQpJbiBhZGRpdGlvbiB0byB0aGUgRU1BLCBwYXJ0aWNpcGFudHMgYWxzbyBjb21wbGV0ZWQgdGhlIFNSRVQuIFRoaXMgaXMgYSBsYWIgYmFzZWQgbWVtb3J5IGJpYXMgbWVhc3VyZS4gV2Ugd2FudCB0byBjaGVjayB3aGV0aGVyIG91ciBtZW1vcnkgYmlhcyBtZWFzdXJlcyBmcm9tIHJlYWwtbGlmZSBhcmUgbGlua2VkIHRvIG9uZXMgZnJvbSB0aGUgbGFiIGluIHRoaXMgc3VwcGxlbWVudGFyeSBhbmFseXNpcy4gDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KCdoYXZlbicpDQpzcmV0X2ZpbGUgPSBmaWxlLnBhdGgoIlo6LyIsICJpbmJveCIsICJ0cmFuc2Zlci0yMDIzLTEyLTA3LTAyLTE1LXBtIiwgJ01FREFMX3ByZSBhbmQgcG9zdCBxdWVzdCBhbmQgcmVtb3RlIHJlY2FsbF93b3JrZmlsZSEhX2ZvciBwYXBlciBvbmx5IHZhci5zYXYnKQ0Kc3JldF9kYXRhID0gcmVhZF9zYXYoc3JldF9maWxlKSANCnNyZXRfZGF0YSA9IHNyZXRfZGF0YSAlPiUgc2VsZWN0KGMoMSw0KSkgJT4lIGRpc3RpbmN0KCkNCg0KZGZfbWVkYWxfcmVjX2NvcjEgPSBkZl9tZWRhbF9jbGVhbiAlPiUNCiAgZHBseXI6OnNlbGVjdChzdWJqZWN0Y29kZSwgcG9zX21vb2QsIHJlY19tZW1fcG9zX21vb2RfbGFnKSAlPiUNCiAgbmEub21pdCgpICU+JSANCiAgZHBseXI6Omdyb3VwX2J5KHN1YmplY3Rjb2RlKSAlPiUNCiAgZHBseXI6Om11dGF0ZShjb3JyID0gIHRyeUNhdGNoKGNvcihyZWNfbWVtX3Bvc19tb29kX2xhZywgcG9zX21vb2QpLCB3YXJuaW5nID0gZnVuY3Rpb24oZSkgTkEpLA0KICAgICAgICAgICAgICAgIG1vZGVsX3R5cGUgPSAiUEFfUkVDIikgJT4lIA0KICBkcGx5cjo6c2VsZWN0KHN1YmplY3Rjb2RlLCBjb3JyLCBtb2RlbF90eXBlKSAlPiUgDQogIGRwbHlyOjpkaXN0aW5jdCgpICAlPiUgdW5ncm91cCgpDQoNCg0KZGZfbWVkYWxfcmVjX2NvcjIgPSBkZl9tZWRhbF9jbGVhbiAlPiUNCiAgZHBseXI6OnNlbGVjdChzdWJqZWN0Y29kZSwgbmVnX21vb2QsIHJlY19tZW1fbmVnX21vb2RfbGFnKSAlPiUNCiAgbmEub21pdCgpICU+JSANCiAgZHBseXI6Omdyb3VwX2J5KHN1YmplY3Rjb2RlKSAlPiUNCiAgZHBseXI6Om11dGF0ZShjb3JyID0gIHRyeUNhdGNoKGNvcihyZWNfbWVtX25lZ19tb29kX2xhZywgbmVnX21vb2QpLCB3YXJuaW5nID0gZnVuY3Rpb24oZSkgTkEpLA0KICAgICAgICAgICAgICAgIG1vZGVsX3R5cGUgPSAiTkFfUkVDIikgJT4lIA0KICBkcGx5cjo6c2VsZWN0KHN1YmplY3Rjb2RlLCBjb3JyLCBtb2RlbF90eXBlKSAlPiUgDQogIGRwbHlyOjpkaXN0aW5jdCgpICU+JSB1bmdyb3VwKCkNCg0KDQpkZl9tZWRhbF9yZW1fY29yMSA9IGRmX21lZGFsX2NsZWFuICU+JQ0KICBkcGx5cjo6c2VsZWN0KHN1YmplY3Rjb2RlLCBwb3NfbW9vZCwgcmVtX21lbV9wb3NfbW9vZF9sYWcpICU+JQ0KICBuYS5vbWl0KCkgJT4lIA0KICBkcGx5cjo6Z3JvdXBfYnkoc3ViamVjdGNvZGUpICU+JQ0KICBkcGx5cjo6bXV0YXRlKGNvcnIgPSB0cnlDYXRjaChjb3IocmVtX21lbV9wb3NfbW9vZF9sYWcsIHBvc19tb29kKSwgd2FybmluZyA9IGZ1bmN0aW9uKGUpIE5BKSwNCiAgICAgICAgICAgICAgICBtb2RlbF90eXBlID0gIlBBX1JFTSIpICU+JSANCiAgZHBseXI6OnNlbGVjdChzdWJqZWN0Y29kZSwgY29yciwgbW9kZWxfdHlwZSkgJT4lIA0KICBkcGx5cjo6ZGlzdGluY3QoKQ0KDQpkZl9tZWRhbF9yZW1fY29yMiA9IGRmX21lZGFsX2NsZWFuICU+JQ0KICBkcGx5cjo6c2VsZWN0KHN1YmplY3Rjb2RlLCBuZWdfbW9vZCwgcmVtX21lbV9uZWdfbW9vZF9sYWcpICU+JQ0KICBuYS5vbWl0KCkgJT4lIA0KICBkcGx5cjo6Z3JvdXBfYnkoc3ViamVjdGNvZGUpICU+JQ0KICBkcGx5cjo6bXV0YXRlKGNvcnIgPSB0cnlDYXRjaChjb3IocmVtX21lbV9uZWdfbW9vZF9sYWcsIG5lZ19tb29kKSwgd2FybmluZyA9IGZ1bmN0aW9uKGUpIE5BKSwNCiAgICAgICAgICAgICAgICBtb2RlbF90eXBlID0gIk5BX1JFTSIpICU+JSANCiAgZHBseXI6OnNlbGVjdChzdWJqZWN0Y29kZSwgY29yciwgbW9kZWxfdHlwZSkgJT4lIA0KICBkcGx5cjo6ZGlzdGluY3QoKQ0KDQoNCmRmX2NvcnMgPSByYmluZGxpc3QobGlzdChkZl9tZWRhbF9yZWNfY29yMSwgZGZfbWVkYWxfcmVjX2NvcjIsIGRmX21lZGFsX3JlbV9jb3IxLCBkZl9tZWRhbF9yZW1fY29yMikpDQoNCmRmX3JlZiA9IG1lcmdlKHNyZXRfZGF0YSwgZGZfY29ycywgYnkueCA9ICdzdWJqZWN0JywgYnkueSA9ICdzdWJqZWN0Y29kZScpDQpkZl9yZWYgPSBkZl9yZWYgJT4lIHJlbmFtZShTUkVUID0gU1JFVF9CaWFzR290bGliX25lZykgJT4lIGRwbHlyOjptdXRhdGUoZ3JvdXAgPSBpZmVsc2Uoc3ViamVjdDw4MDAsICJyZW1pdHRlZCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2Uoc3ViamVjdD49OTAwLCAiY29udHJvbCIsICdkZXByZXNzZWQnKSkgKQ0KDQoNCmZvciAobW9kX3R5cGUgaW4gYygiUEFfUkVDIiwgIlBBX1JFTSIsICJOQV9SRUMiLCAiTkFfUkVNIikpew0KICBwcmludChtb2RfdHlwZSkNCiAgcHJpbnQoc3VtbWFyeShsbShTUkVUIH4gY29ycipncm91cCwgZGF0YSA9IGRmX3JlZiAlPiUgZmlsdGVyKG1vZGVsX3R5cGUgPT0gbW9kX3R5cGUpKSkpDQp9DQoNCg0KYGBgDQoNCg0KIyMgUmVsYXRpdmUgQmlhcw0KDQpIZXJlIHdlIHdhbnQgdG8gY2hlY2sgZm9yIHRoZSByZWxhdGl2ZSBOQS9QQSBiaWFzLiBTbyB3ZSBleHRhY3QgdGhlIHJhbmRvbSBlZmZlY3RzIGZyb20gdGhlIG1vZGVscyB0byBnZXQgdGhlIHNsb3BlcyBmb3IgZWFjaCBzdWJqZWN0LCBhbmQgdGhlbiBjb21wYXJlIHRoZSBOQS9QQSBzbG9wZXMuIFRoaXMgdGVsbHMgdXMgaWYgdGhlcmVzIGEgYmlhcyBiZXR3ZWVuIG5lZ2F0aXZlIGFuZCBwb3NpdGl2ZSBtZW1vcnkuDQoNCmBgYHtyfQ0KDQojIEdldCBpbmRpdmlkdWFsIHNsb3Blcw0KcG9zX3JlY19yZWYgPSBhcy5kYXRhLmZyYW1lKHJhbmVmKGgxX3Bvc19yZWNlbnRfbW9kZWxzW1syXV0pKSAlPiUgZmlsdGVyKHRlcm0hPScoSW50ZXJjZXB0KScpICU+JSBzZWxlY3QoYygzOjUpKQ0KcG9zX3JlbV9yZWYgPSBhcy5kYXRhLmZyYW1lKHJhbmVmKGgxX3Bvc19yZW1vdGVfbW9kZWxzW1syXV0pKSAlPiUgZmlsdGVyKHRlcm0hPScoSW50ZXJjZXB0KScpICU+JSBzZWxlY3QoYygzOjUpKQ0KbmVnX3JlY19yZWYgPSBhcy5kYXRhLmZyYW1lKHJhbmVmKGgxX25lZ19yZWNlbnRfbW9kZWxzW1s0XV0pKSAlPiUgZmlsdGVyKHRlcm0hPScoSW50ZXJjZXB0KScpICU+JSBzZWxlY3QoYygzOjUpKQ0KbmVnX3JlbV9yZWYgPSBhcy5kYXRhLmZyYW1lKHJhbmVmKGgxX25lZ19yZW1vdGVfbW9kZWxzW1s0XV0pKSAlPiUgZmlsdGVyKHRlcm0hPScoSW50ZXJjZXB0KScpICU+JSBzZWxlY3QoYygzOjUpKQ0KcG9zX3JlY19yZWYkbW9kID0gIlBBX1JFQyINCnBvc19yZW1fcmVmJG1vZCA9ICJQQV9SRU0iDQpuZWdfcmVjX3JlZiRtb2QgPSAiTkFfUkVDIg0KbmVnX3JlbV9yZWYkbW9kID0gIk5BX1JFTSINCg0KIyBQdXQgdG9nZXRoZXIgaW50byBhIG5ldyBkYXRhIGZyYW1lDQpkZl9yZWYgPSByYmluZGxpc3QobGlzdChwb3NfcmVjX3JlZiwgcG9zX3JlbV9yZWYsIG5lZ19yZWNfcmVmLCBuZWdfcmVtX3JlZikpDQpkZl9yZWYgPSBkZl9yZWYgJT4lIA0KICBkcGx5cjo6bXV0YXRlKHN1YiA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGdycCkpKSAlPiUNCiAgZHBseXI6Om11dGF0ZShncm91cCA9IGlmZWxzZShzdWIgPD0gODAwLCAicmVtaXR0ZWQiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2Uoc3ViPj05MDAsICJjb250cm9sIiwgJ2RlcHJlc3NlZCcpKSApDQoNCmRmX3JlZl9yZWMgPSBkZl9yZWYgJT4lIGZpbHRlcihtb2QgPT0gJ1BBX1JFQycgfCBtb2Q9PSdOQV9SRUMnKQ0KZGZfcmVmX3JlbSA9IGRmX3JlZiAlPiUgZmlsdGVyKG1vZCA9PSAnUEFfUkVNJyB8IG1vZD09J05BX1JFTScpDQpzdW1tYXJ5KGxtZXIoY29uZHNkIH4gbW9kKmdyb3VwICsgKDF8c3ViKSwgZGF0YSA9IGRmX3JlZl9yZWMpKQ0Kc3VtbWFyeShsbWVyKGNvbmRzZCB+IG1vZCpncm91cCArICgxfHN1YiksIGRhdGEgPSBkZl9yZWZfcmVtKSkNCmBgYA0KDQoNCg0KIyBQbG90cw0KDQpGaXJzdCB3ZSBzZXQgb3VyIHRoZW1lIGFuZCBmaXggdGhlIGRhdGEgZm9yIHRoZSBmaWd1cmVzIHdlIHdhbnQNCmBgYHtyfQ0KIyBUaGVtZQ0KZ2d0aGVtZSA9IHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLCANCiAgICAgICAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiKSwgDQogICAgICAgICAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmV5OTAiKSwNCiAgICAgICAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyZXkxMDAiKSwNCiAgICAgICAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiZ3JleTgwIiwgZmlsbCA9ICJ0cmFuc3BhcmVudCIpKQ0KDQojIEVzdGltYXRlIHRoZSBTRA0KZGZfbWVkYWxfY2xlYW4yID0gZGZfbWVkYWxfY2xlYW4gJT4lIA0KICBtdXRhdGUocG9zX21vb2Rfc2QgPSBpZmVsc2UoIChwb3NfbW9vZF9jc19sYWdfcmVjID4gKG1lYW4ocG9zX21vb2RfY3NfbGFnX3JlYywgbmEucm09VCkrc2QocG9zX21vb2RfY3NfbGFnX3JlYywgbmEucm09VCkpKSwgIisxU0QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSggKHBvc19tb29kX2NzX2xhZ19yZWMgPCAobWVhbihwb3NfbW9vZF9jc19sYWdfcmVjLCBuYS5ybT1UKS1zZChwb3NfbW9vZF9jc19sYWdfcmVjLCBuYS5ybSA9VCkpKSwgIi0xU0QiLCAiTWVhbiIpKSkgJT4lIA0KICAgIG11dGF0ZShuZWdfbW9vZF9zZCA9IGlmZWxzZSggKG5lZ19tb29kX2NzX2xhZ19yZWMgPiAobWVhbihuZWdfbW9vZF9jc19sYWdfcmVjLCBuYS5ybT1UKStzZChuZWdfbW9vZF9jc19sYWdfcmVjLCBuYS5ybT1UKSkpLCAiKzFTRCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKCAobmVnX21vb2RfY3NfbGFnX3JlYyA8IChtZWFuKG5lZ19tb29kX2NzX2xhZ19yZWMsIG5hLnJtPVQpLXNkKG5lZ19tb29kX2NzX2xhZ19yZWMsIG5hLnJtID1UKSkpLCAiLTFTRCIsICJNZWFuIikpKQ0KDQojIEZpeCBmYWN0b3IgbGV2ZWxzDQpkZl9tZWRhbF9jbGVhbjIkQ29uZGl0aW9uID0gIGZhY3RvcihkZl9tZWRhbF9jbGVhbjIkY29uZGl0aW9uLCBsZXZlbHM9YygnY29udHJvbCcsICdyZW1pdHRlZCcsICdkZXByZXNzZWQnICksIGxhYmVscz1jKCdOZXZlci1EZXByZXNzZWQnLCAnUmVtaXR0ZWQnLCAnRGVwcmVzc2VkJykpDQpkZl9tZWRhbF9jbGVhbjIkcG9zX21vb2Rfc2QgPSAgZmFjdG9yKGRmX21lZGFsX2NsZWFuMiRwb3NfbW9vZF9zZCwgbGV2ZWxzPWMoJy0xU0QnLCAnTWVhbicsICcrMVNEJyApKQ0KZGZfbWVkYWxfY2xlYW4yJG5lZ19tb29kX3NkID0gIGZhY3RvcihkZl9tZWRhbF9jbGVhbjIkbmVnX21vb2Rfc2QsIGxldmVscz1jKCctMVNEJywgJ01lYW4nLCAnKzFTRCcgKSkNCg0KDQpgYGANCg0KIyMjIFBBLUNVUi1SRUMNCmBgYHtyfQ0KDQojIFBsb3QNCnBsb3RfcGFfcmVjID0gZ2dwbG90KGRmX21lZGFsX2NsZWFuMiwgYWVzKHggPSByZWNfbWVtX3Bvc19tb29kX2NfbGFnLCB5PXBvc19tb29kX2MsIGNvbG9yID0gcG9zX21vb2Rfc2QsIGZpbGwgPSBwb3NfbW9vZF9zZCkpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJywgYWxwaGEgPSAwLjE1KSArDQogIGxhYnMoIHggPSBicXVvdGUocGFzdGUoUkVDW1BNXSwgIiAoc3ViamVjdC1jZW50ZXJlZCBhLnUuKSIpKSwgeSA9ICJQTSAoc3ViamVjdC1jZW50ZXJlZCBhLnUuKSIsIGNvbG9yID0gYnF1b3RlKENVUltQTV0pLCBmaWxsID0gYnF1b3RlKENVUltQTV0pICkgKw0KICBnZ3RoZW1lICsgDQogIGZhY2V0X2dyaWQoLn5Db25kaXRpb24pIA0KcGxvdF9wYV9yZWMNCmBgYA0KDQojIyMgUEEtQ1VSLVJFQw0KDQpgYGB7cn0NCg0KIyBQbG90DQpwbG90X25hX3JlYyA9IA0KICBnZ3Bsb3QoZGZfbWVkYWxfY2xlYW4yLCBhZXMoeCA9IHJlY19tZW1fbmVnX21vb2RfY19sYWcsIHk9bmVnX21vb2RfYywgY29sb3IgPSBuZWdfbW9vZF9zZCwgZmlsbCA9IG5lZ19tb29kX3NkKSkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nLCBhbHBoYSA9IDAuMTUpICsNCiAgbGFicyggeCA9IGJxdW90ZShwYXN0ZShSRUNbJ05NJ10sICIgKHN1YmplY3QtY2VudGVyZWQgYS51LikiKSksIHkgPSAiTk0gKHN1YmplY3QtY2VudGVyZWQgYS51LikiLCBjb2xvciA9IGJxdW90ZShDVVJbIk5NIl0pLCBmaWxsID0gYnF1b3RlKENVUlsiTk0iXSkgKSsNCiAgZ2d0aGVtZSArIA0KICBmYWNldF9ncmlkKC5+Q29uZGl0aW9uKSANCnBsb3RfbmFfcmVjDQpgYGANCg0KIyMjIENvbWJpbmVkIFBsb3QgZm9yIHB1Yg0KYGBge3J9DQpnZ2FycmFuZ2UoTkEsIHBsb3RfcGFfcmVjLCBOQSwgIHBsb3RfbmFfcmVjLA0KICAgICAgICAgIHdpZHRocz1jKDAuMDUsIDEsIDAuMDUsIDEpLCBuY29sID0gMiwgbnJvdyA9IDIsDQogICAgICAgICAgbGFiZWxzPWMoIkEiLCBOQSwgIkIiKSkNCmdnc2F2ZSgiZmlndXJlcy9maWd1cmVfMl90aHJlZXdheUludGVyYWN0aW9uLnBkZiIsIGRldmljZSA9ICdwZGYnLCBkcGkgPSAzMjAsIGhlaWdodCA9IDYpDQoNCmBgYA0KDQoNCiMgU3lzdGVtIEluZm8NCg0KYGBge3J9DQpzZXNzaW9uSW5mbygpDQoNCmBgYA0KDQoNCg0KDQo=